Question

My webapp has a non-empty production beans.xml under src/main/resources/META-INF. Now, for my tests, I need to swap out 1 bean with an alternative.

Where do I put this test beans.xml which contains just this and nothing more?

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
  <alternatives>
    <class>...MyTestReplacement</class>
  </alternatives>
</beans>

I tried under src/test/resources/META-INF but that is ignored. I am using arquillian and my test classpath is added to the ShrinkWrap.

Was it helpful?

Solution 2

Don't use @Alternative, but use @Specializes. Just put the @Specializes bean only in your test classpath and it will automatically replace the real bean. No need to mess around with beans.xml.

OTHER TIPS

Even though it's already accepted, ill post you the solution I found. I had the same problem, and using @Specializes was no option for me, because I had many mocks with several methods, thus create for each one a class was a bit overkill....

So in my test I have a ResourceMock:

@Produces
@Alternative
public IResource createResource() {
    Resource resource = mock(Resource.class);
    when(resource.getLocalized(anyString())).then(AdditionalAnswers.returnsFirstArg());
    return resource;
}

With the following ShrinkWrap I was able to load those @Alternative bean only during the test: (no beans.xml in the test dir needed!)

return ShrinkWrap
            .create(JavaArchive.class)
            .addPackages(true, "some.package.with.classes")
            .addAsManifestResource(
                    new StringAsset(
                            "<alternatives><class>my.testclass.with.alternatives</class></alternatives>"),
                    "beans.xml");

And that's it.

Or, if you need to use @Alternative, you can use a shrinkwrap command .alternativeClass. You can see the following example in the Arquillian-showcase, cdi-ejb subproject. Include this dependency in your pom:

    <dependency>
        <groupId>org.jboss.shrinkwrap.descriptors</groupId>
        <artifactId>shrinkwrap-descriptors-impl</artifactId>
        <scope>test</scope>
    </dependency>

Then use this type of @Deployment (for Glassfish):

    @Deployment
    public static WebArchive createDeploymentForGlassFish() {
    BeansDescriptor beansXml = Descriptors.create(BeansDescriptor.class);

    return ShrinkWrap.create(WebArchive.class)
            .addClasses(FireAndForget.class, FireAndForgetBean.class, BlockingFireAndForgetAlternativeBean.class)
            .addAsWebInfResource(
                    new StringAsset(beansXml.alternativeClass(BlockingFireAndForgetAlternativeBean.class).exportAsString()),
                    beansXml.getDescriptorName());
}

Hope that helps!

In my case I used the code from bellow to specify which beans.xml file to include:

JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
                .addClasses(AutoService.class, AutoServiceCallerImp1.class, AutoServiceCallerImp2.class)
                .addAsManifestResource("META-INF/test.beans.xml", "beans.xml");
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top