I have an interface Repository
with two implementations, DBRepository
and UTRepository
. UTRepository
is annotated with @Alternative
and I'm trying to use it in a JUnit test.
The test class:
@RunWith(Arquillian.class)
public class UserServiceTest {
@Inject
private UserService service;
@Deployment
public static JavaArchive createDeployment() {
return ShrinkWrap.create(JavaArchive.class)
.addClasses(Repository.class, UserService.class, UTRepository.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
@Test
public void addCharacterTest() {
service.addCharacter(1L, Mockito.mock(GameCharacter.class));
}
}
The class under test:
public class UserService {
@Inject
Repository repository;
@Transactional
public void addCharacter(Long userId, GameCharacter character) {
User user = repository.readById(userId, User.class);
user.addCharacter(character);
repository.update(user);
}
}
My beans.xml
file (placed in src/test/webapp/WEB-INF/beans.xml):
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_2.xsd"
bean-discovery-mode="all">
<alternatives>
<class>org.package.name.UTRepository</class>
</alternatives>
</beans>
When I try to run the test, I get the exception:
org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type Repository with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject org.package.name.services.UserService.repository
at org.package.name.services.UserService.repository(UserService.java:0)
at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:359)
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:281)
at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:134)
at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:155)
at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:518)
at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:68)
at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:66)
at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:63)
at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:56)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
What is the problem?
The solution you found works well, so just for completness.
Basically you need to add beans.xml
which will enable your alternative. EmptyAsset.INSTANCE
will result in empty beans.xml which won't cut it in this case.
However, in your solution, the beans.xml
you placed under src/test/webapp/WEB-INF/beans.xml
does nothing. If you want to leverage an existing beans.xml
file, you can use:
addAsManifestResource(File resource, String target)
which adds given File
as with name of target
addAsManifestResource(Package resourcePackage, String resourceName, String target)
which allows you to specify just the package where the file is, then its name and file the name under which you want it in your deployment