Quickstart

Learn how to create and run Citrus integration tests in just a few minutes. You can choose from a set of supported runtimes (JUnit, TestNG, Quarkus, SpringBoot, JBang) and domain specific languages (Java, XML, YAML, Groovy, Cucumber).

When writing a Citrus test you can choose from a set of supported programming languages and domain specific languages (DSL).

The Citrus Java DSL represents the most powerful way to write tests. Citrus provides a set of classes and methods to leverage the test code in form of a fluent API. Users can simply configure a test action with the different options using a fluent builder pattern style DSL.

In addition to that you can also write Citrus tests with XML, Groovy, YAML, Cucumber (Gherkin), Spring XML declaration files that get loaded as part of the test runtime. These test sources represent a more declarative approach of writing tests in Citrus. You do not necessarily need to know how to code Java when using one of these languages, but you may be limited in terms of customization opportunities.

See the following example to explore the different test source languages in Citrus.

Java
@CitrusTest
public void helloWorldTest() {
    variable("user", "Citrus");

    $(echo().message("Hello from ${user}!"));
}
XML
<test name="HelloWorldTest" xmlns="http://citrusframework.org/schema/xml/testcase">
    <variables>
      <variable name="user" value="Citrus"/>
    </variables>
    <actions>
      <echo message="Hello from ${user}!"/>
    </actions>
</test>
YAML
name: HelloWorldTest
variables:
  - name: user
    value: Citrus
actions:
  - echo:
      message: "Hello from ${user}!"
Groovy
name "HelloWorldTest"

variables {
   user="Citrus"
}

actions {
    $(echo().message('Hello from ${user}!'))
}
Cucumber
Feature: HelloWorldTest

  Background:
    Given variables
      | user | Citrus |

  Scenario: Should Say Hello
    Then print "Hello from ${user}!"

The easiest way to run a Citrus test is to use the Citrus JBang CLI tooling. This requires no project setup and no dependency management because everything is handled by JBang out of the box.

Run with JBang
jbang citrus@citrusframework/citrus run helloWorld.yaml

TIP: You can install Citrus as a JBang app on your machine. This makes using the Citrus CLI even more comfortable because you can just call citrus run for instance.

Install Citrus JBang app
jbang trust add https://github.com/citrusframework/citrus/
jbang app install citrus@citrusframework/citrus

TIP: The init> command creates a sample test in the chosen language for you.

Init and run test
citrus init helloWorld.yaml

citrus run helloWorld.yaml

The Citrus JBang support is fantastic to do fast prototyping. You just focus on writing the Citrus test code with fast and easy test execution via JBang. Once you are happy with the test you may want to move on to use one of the supported runtimes in Citrus in order to integrate the test into your project build lifecycle (e.g. via Maven and JUnit).

The Citrus test case is nothing but a normal Java unit test. Citrus integrates with standard unit test frameworks such as JUnit, TestNG or Cucumber as a runtime.

In addition to that Citrus also works with @QuarkusTest and @SpringBootTest annotated classes.

Most Java developers are familiar with at least one of the standard tools. Everything you can do with JUnit or TestNG you can do with Citrus tests, too. For instance, you can integrate the Citrus tests in a Maven build, run and debug Citrus from your favorite Java IDE or include Citrus tests into a continuous build pipeline.

Citrus supports multiple runtimes. The most prominent nowadays probably is JUnit Jupiter.

JUnit
import org.citrusframework.TestCaseRunner;
import org.citrusframework.TestActionSupport;
import org.citrusframework.annotations.CitrusResource;
import org.citrusframework.annotations.CitrusTest;
import org.citrusframework.junit.jupiter.CitrusSupport;
import org.junit.jupiter.api.Test;

@CitrusSupport
public class HelloServiceIT implements TestActionSupport {

    @CitrusResource
    private TestCaseRunner t;

    @Test
    @CitrusTest
    public void shouldSayHello() {
        t.createVariable("user", "Citrus");

        t.run(echo("Hello from ${user}!"));
    }
}
QuarkusTest
import org.citrusframework.TestCaseRunner;
import org.citrusframework.TestActionSupport;
import org.citrusframework.annotations.CitrusResource;
import org.citrusframework.quarkus.CitrusSupport;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
@CitrusSupport
public class HelloServiceIT implements TestActionSupport {

    @CitrusResource
    private TestCaseRunner t;

    @Test
    void shouldSayHello() {
        t.createVariable("user", "Citrus");

        t.run(echo("Hello from ${user}!"));
    }
}
SpringBoot
import org.citrusframework.TestCaseRunner;
import org.citrusframework.TestActionSupport;
import org.citrusframework.annotations.CitrusResource;
import org.citrusframework.config.CitrusSpringConfig;
import org.citrusframework.junit.jupiter.spring.CitrusSpringSupport;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.junit.jupiter.api.Test;

@SpringBootTest
@CitrusSpringSupport
@ContextConfiguration(classes = {CitrusSpringConfig.class})
public class HelloServiceIT implements TestActionSupport {

    @CitrusResource
    private TestCaseRunner t;

    @Test
    void shouldSayHello() {
        t.createVariable("user", "Citrus");

        t.run(echo("Hello from ${user}!"));
    }
}
TestNG
import org.testng.annotations.Test;
import org.citrusframework.TestActionSupport;
import org.citrusframework.annotations.CitrusTest;
import org.citrusframework.testng.TestNGCitrusSupport;

public class HelloServiceIT extends TestNGCitrusSupport implements TestActionSupport {

    @Test
    @CitrusTest
    public void shouldSayHello() {
        variable("user", "Citrus");

        $(echo("Hello from ${user}!"));
    }
}
JUnit4
import org.citrusframework.TestActionSupport;
import org.citrusframework.annotations.CitrusTest;
import org.citrusframework.junit.spring.JUnit4CitrusSupport;
import org.junit.Test;

public class HelloServiceIT extends JUnit4CitrusSupport implements TestActionSupport {

    @Test
    @CitrusTest
    public void shouldSayHello() {
        variable("user", "Citrus");

        $(echo("Hello from ${user}!"));
    }
}
Cucumber
@RunWith(Cucumber.class)
@CucumberOptions(
    extraGlue = { "org.citrusframework.cucumber" },
    plugin = { "pretty", "org.citrusframework.cucumber.CitrusReporter" } )
public class HelloServiceIT {

}

Now that you know how to run the Citrus tests it is time to explore the framework capabilities. In a typical use case scenario Citrus connects to different messaging transports and technologies such as Kafka, Http REST, JMS, Spring, Apache Camel, Testcontainers, Kubernetes, Knative, Selenium and many more.

Citrus combines with many frameworks and libraries and provides ready-to-use components and test actions to leverage the full power of integration testing. It is very easy to create an integration test case for messaging where the test sends a message to Kafka for instance to verify its outcome via response message validation.

MyTest.java
import org.citrusframework.TestActionSupport;
import org.citrusframework.TestCaseRunner;
import org.citrusframework.annotations.CitrusResource;

public class MyTest implements Runnable, TestActionSupport {

    @CitrusResource
    TestCaseRunner t;

    @Override
    public void run() {
        t.when(
            http().client("http://localhost:8080/test")
                    .send()
                    .post()
                    .contentType("text/plain")
                    .body("Hello from Citrus!")
        );

        t.then(
            receive().endpoint("kafka:my-topic")
                    .message()
                    .body("Hello from Citrus!")
        );

        t.and(
            http().client("http://localhost:8080/test")
                .receive()
                .response(HttpStatus.OK));
    }
}

As you can see the test leverages several Citrus features like sending/receiving messages with different message transports. Receiving a message always comes with an expected message content, so Citrus performs a powerful message validation on body and header content. Citrus is able to handle different message types such as XML, Json, Plaintext, YAML, CSV and more.

You can easily integrate the test into your project with one of the supported runtimes, or you can just run the test without any project setup with JBang.

Run MyTest.java
citrus run MyTest.java

Still having trouble to use Citrus? Please reach out to get some help!