Consider the following Quarkus application:
@ApplicationScoped
@Path("/hello")
public class HelloService {
@Inject
Helper helper;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String sayHello(){
return "Hello "+helper.getName();
}
}
@Dependent
public class Helper {
public String getName() {
return "World";
}
}
and the following Test:
@QuarkusTest
@TestHTTPEndpoint(HelloService.class)
public class HelloQuarkusTest {
@Test
void testSayHello(){
given().when().then().body(is("Hello World"));
}
}
Everything's fine up to this point. The service and its helper are of course a bit more complicated than that in reality. So I want to have some unit tests. If I write a unit test for the service like so:
@EnableAutoWeld
@ExtendWith(MockitoExtension.class)
class HelloUnitTest {
@Inject
HelloService helloService;
@Produces @Mock
@ExcludeBean // don't use the real bean, use this instead
Helper helperMock;
@Test
void testSayHello(){
when(helperMock.getName()).thenReturn("Mock");
final String actual = helloService.sayHello();
assertThat(actual).isEqualTo("Hello Mock");
}
}
Then the unit test is green, but suddenly the @QuarkusTest
fails, because it finds both the real Helper
implementation and the producer field from the unit test and consequently throws an AmbiguousResolutionException
:
java.lang.RuntimeException: java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[error]: Build step io.quarkus.arc.deployment.ArcProcessor#validate threw an exception: javax.enterprise.inject.spi.DeploymentException: javax.enterprise.inject.AmbiguousResolutionException: Ambiguous dependencies for type com.example.Helper and qualifiers [@Default]
- java member: com.example.HelloService#helper
- declared on CLASS bean [types=[com.example.HelloService, java.lang.Object], qualifiers=[@Default, @Any], target=com.example.HelloService]
- available beans:
- CLASS bean [types=[java.lang.Object, com.example.Helper], qualifiers=[@Default, @Any], target=com.example.Helper]
- PRODUCER FIELD bean [types=[java.lang.Object, com.example.Helper], qualifiers=[@Default, @Any], target=com.example.Helper com.example.weld.HelloUnitTest.helperMock, declaringBean=com.example.weld.HelloUnitTest]
This happens even if the tests are in different packages. To some extend I understand why scanning more than one class/package is intended for a @QuarkusTest
, but I don't like it in this case.
So my question is:
How can I configure what beans/classes/packages a
@QuarkusTest
picks up and which it ignores?
I have tried playing around with the Arc settings in application-test.properties
, but so far have not found the right combination of properties.
You could try to add all the weld-junit unit tests in a specific package and exclude this package from quarkus discovery via
quarkus.arc.exclude-types
; i.e. something like%test.quarkus.arc.exclude-types=org.acme.unit.tests.**
.