Lesson learned re. testing in Java with Mockito and JUnit5
FYI for anyone using the Java SDK that wants to unit test with JUnit 5 instead of version 4, I was able to adapt the HelloWorldWorkflowTest to run with the following:
build.gradle:
dependencies {
implementation 'io.temporal:temporal-sdk:1.0.6'
// Testing dependencies
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1'
testImplementation 'org.mockito:mockito-core:3.9.0'
testImplementation 'io.temporal:temporal-testing:1.0.6'
testImplementation 'io.temporal:temporal-testing-junit5:1.0.6'
}
HelloWorldWorkflowTest.java:
package helloworldapp;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.withSettings;
import static org.mockito.Mockito.verify;
import io.temporal.testing.TestWorkflowExtension;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
class HelloWorldWorkflowTest {
private static final Format format = mock(Format.class, withSettings().withoutAnnotations());
@RegisterExtension
public static final TestWorkflowExtension workflowExtension =
TestWorkflowExtension.newBuilder()
.setWorkflowTypes(HelloWorldWorkflowImpl.class)
.setActivityImplementations(format)
.build();
@Test
void testGetGreeting(HelloWorldWorkflow workflow) {
workflow.getGreeting("test");
verify(format).composeGreeting("test");
}
}
When mocking Activity interfaces using Mockito you need to tell it not to copy over the annotations, eg:
Mockito.mock(Format.class, withSettings().withoutAnnotations())
Otherwise you’ll get some nasty errors that look like this:
java.lang.IllegalArgumentException: Found @ActivityMethod annotation on "public java.lang.String helloworldapp.Format$MockitoMock$255547570.composeGreeting(java.lang.String)" This annotation can be used only on the interface method it implements.
This may be common knowledge but I struggled for an hour or so to get it to work, so I hope this is helpful for someone.