🚀 New! Kestra raises $3 million to grow Learn more

Kestra is build from the inception with unit tests in mind. A task must be unit testable to avoid regression and bugs. So we provide 2 ways to unit test your tasks. Both will be regular Micronaut tests so must be annotated with @MicronautTest.

Unit test a RunnableTask

This is the most common way to test a RunnableTask. You create your RunnableTask, and test output or Exception. This will cover most of the case. Here is an example:


class ExampleTest {
    private RunContextFactory runContextFactory;

    void run() throws Exception {
        RunContext runContext = runContextFactory.of(ImmutableMap.of("variable", "John Doe"));

        Example task = Example.builder()
            .format("Hello {{ variable }}")

        Example.Output runOutput = task.run(runContext);

        assertThat(runOutput.getChild().getValue(), is(StringUtils.reverse("Hello John Doe")));

The same as any java unit tests, fell free to use any dependencies, test methods, started docker containers, ...

Unit test with a full flow

Maybe you want to add some unit test with a full flow, in some rare case, it can be necessary (mostly for FlowableTask).

Here is an example:

class ExampleRunnerTest {
    protected MemoryRunner runner;

    protected RunnerUtils runnerUtils;

    protected LocalFlowRepositoryLoader repositoryLoader;

    private void init() throws IOException, URISyntaxException {

    void flow() throws TimeoutException {
        Execution execution = runnerUtils.runOne(null, "io.kestra.templates", "example");

        assertThat(execution.getTaskRunList(), hasSize(3));
        assertThat(((Map<String, Object>)execution.getTaskRunList().get(2).getOutputs().get("child")).get("value"), is("task-id"));

With this, you will:

  • Inject all dependencies with @Inject.
  • On init(), load all the flow on the src/resources/flow directory.
  • Run a full execution with Execution execution = runnerUtils.runOne(null, "io.kestra.templates", "example");. The first parameter is for the tenantId which can be null on tests.

With this execution, you can look at all the properties you want to control (status, taskRunList number, outputs, ...)

To make it work, you need to have an application.yml files with this minimum configuration:

    type: memory
    type: memory
    type: local
      base-path: /tmp/unittest

And these dependencies on your build.gradle:

    testImplementation group: "io.kestra", name: "core", version: kestraVersion
    testImplementation group: "io.kestra", name: "repository-memory", version: kestraVersion
    testImplementation group: "io.kestra", name: "runner-memory", version: kestraVersion
    testImplementation group: "io.kestra", name: "storage-local", version: kestraVersion

This will enabled the in memory runner and will run your flow without any others dependencies (kafka, ...).