Is bean discovery for @QuarkusTest configurable?

715 views Asked by At

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.

1

There are 1 answers

0
Martin Kouba On

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.**.