Weld (CDI): where do I put my test-only beans.xml that configures <alternatives>?
-
17-04-2021 - |
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.
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");