Hoi!
The problem I discovered is pretty simple to understand but I can't find a solution.
First let me provide this little snippet.
@Deployment
public static Archive<?> createDeployableArchive () {
JavaArchive jar = ShrinkWrap.create(JavaArchive.class, "whoCares.jar");
// enable CDI
jar.addAsManifestResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml");
// Some persistence
jar.addAsManifestResource("test-persistence.xml", "persistence.xml");
// Now the interisting part (simplified):
jar.addClass(RegistrationService.class) // This one should be tested
.addClass(RegistrationException.class) // Will be thrown on error.
.addClass(UserDAO.class) // Used by RegService
.addClass(User.class) // JPA Entity
// ...
// ... This scenario goes without interfaces, inheritance, DTOs, different
// ... types of exceptions for different problem types... That's why the list
// ... is so concise.
// ...
.addClass(RegServiceIntegrationTest.class); // Test class must be included
return jar;
}
Every time you want to test a certain use case, for example registerUser, with arquillian you will have to collect all classes your registration process depends on and put them together in a deployable archive.
Doing this manually will cost time and produce problems and errors, for sure! There are several weak points:
Collecting: Think of a long process with many sub services, exceptions, interfaces, super classes, utility stuff and so on. You will walk over the complete flow to find them all. Honestly, that's a repetitious long term job that will be a pain the... eyes. I had to do it just a few times before I decided to rather start yelling.
Keeping your tests up to date: Imagine you involve a new sub service to your registration chain. You will have to update those damn dependencies and if something goes wrong when you run your integration tests at the end of the day there will be fun digging through sometimes incomplete exception messages (incomplete cause you only know something is missing at some point but not what exactly). If you're lucky a ClassNotFoundException occurs. One change could of course easily affect multiple tests: 1. Let UserDao throw some new fancy runtime exception. 2. Waste your life time.
Problems with adding packages: Adding packages is provided by Shrinkwrap but using it would be a bad Idea. Sometimes, after a long day, you feel lazy and just add complete packages but can you be absolutely sure every class will remain in the same package forever? Another problem is that the term "micro deployment" implies a need for compactness. Whole packages introduce overhead, okay I guess that's the smallest problem here.
How to solve this (Just unqualified thoughts)?
It is kind of banal that all required information already is available in the source code.
The best solution would be something like this:
@Deployment
public static Archive<?> createDeployableArchive () {
JavaArchive jar = ShrinkWrap.create(JavaArchive.class, "whoCares.jar");
// enable CDI
jar.addAsManifestResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml");
// Some persistence
jar.addAsManifestResource("test-persistence.xml", "persistence.xml");
Class<?>[] involved;
involved = Tool.findInvolvedClasses("RegistrationService.java", "registerUser");
jar.addClasses(involved);
return jar;
}
I don't think one can achieve this using reflection as it's necessary to know the exact "flow".
I bet there is a cool tool out there that could be put to an unintended use. There might of course be other ways. Does somebody have an idea? Thanks!