-
1. Re: Test class as a bean
dan.j.allen May 4, 2010 1:27 AM (in response to dan.j.allen)There is a workaround right now. In CDI containers, the test class is picked up as a bean. So it's possible to inject it into itself to get the container-managed instance. Then you could just delegate to a helper method if you want interceptors to be used. Here's an example:
@RunWith(Arquillian.class) public class SampleTestCase { @Inject SampleTestCase instance; @Test public void testMethod() { // call will be intercepted (if interceptor is enabled) instance.helperMethod(); } @SomeInterceptorBinding public void helperMethod() { System.out.println("This line is bugged."); } }
So maybe we aren't really limited after all. I still think it's work asking whether the test case instance should come from the container or not. Then state clearly where we stand on the issue.
-
2. Re: Test class as a bean
dan.j.allen May 4, 2010 1:49 AM (in response to dan.j.allen)Turns out ALR was one neuron firing ahead of me on this one.
ARQ-98: Research possibility of a TestCase Object creation extension point
-
3. Re: Test class as a bean
alrubinger May 4, 2010 1:48 AM (in response to dan.j.allen)I suspect that the test instance as a bean has to be implementation-specific to the target container.
In the Reloaded container, for instance, the test enrichers do nothing. The bean is installed into MC, which in turn handles all injection points. I imagine the same could be true for CDI/Weld. EJB 3.1 might be possible too, with no-interface view used. But for that we'd have to work some container-specific magic and add the proper metadata to get it picked up.
Either way, we're quickly racking up a bunch of differences in the capabilities each container supports. Perhaps as part of the container implementing process each developer should fill a Wiki (from template) describing the annotations honored, run modes, etc.
Definitely like becomes easy when we install test instances as managed beans; then the enrichers have much less to do.
S,
ALR
-
4. Re: Test class as a bean
pmuir May 24, 2010 10:43 AM (in response to dan.j.allen)Dan Allen wrote:
I've always felt this is a bad thing - why would want a interceptor (e.g. security) applied to your test case? I haven't yet come up with a use case for this.
-
5. Re: Test class as a bean
dan.j.allen May 24, 2010 2:42 PM (in response to pmuir)Pete Muir wrote:
Dan Allen wrote:
I've always felt this is a bad thing - why would want a interceptor (e.g. security) applied to your test case? I haven't yet come up with a use case for this.
I was thinking more along the lines of transactions.
Obviously the business method you are calling should have a transaction if it's doing persistence. When you need a transaction in the test is for setting up a fixture via the EntityManager (seeding the database) and also to rollback the change. Given that the focus is really on transactions, we should just concentrate on that issue instead. It's possible to inject a UserTransaction if the container is Java EE compatible, but you don't get it for the embedded CDI container (I think).
Here's the use case.
@Inject UserTransaction utx; @Test public void testAddTask() throws Exception { Assert.assertEquals(agendaEm.createQuery("select count(t) from Task t").getSingleResult(), 0l); Task task = taskManager.getNewTask(); Assert.assertFalse(task.isCompleted()); task.setDescription("Task 1"); taskManager.addTask(); utx.begin(); agendaEm.joinTransaction(); agendaEm.flush(); utx.commit(); Assert.assertNotNull(task.getId()); Assert.assertNotNull(task.getDateCreated()); Assert.assertSame(task, taskManager.getLastTaskAdded()); Assert.assertNotSame(task, taskManager.getNewTask()); utx.begin(); agendaEm.joinTransaction(); Assert.assertEquals(agendaEm.createQuery("select count(t) from Task t").getSingleResult(), 1l); agendaEm.createQuery("delete from Task t").executeUpdate(); utx.commit(); }
-
6. Re: Test class as a bean
pmuir Jun 7, 2010 11:39 PM (in response to dan.j.allen)Sorry for the late reply ;-)
It strikes me that we have this because we have unit testing creep going on. If you instead consider that what you want to test is TaskManager integration with the persistence layer, then you wouldn't want to put your TX logic into the test anyway.
Given that people can use TXs in a test (as you show), I think that is sufficient.
-
7. Re: Test class as a bean
dan.j.allen Jun 7, 2010 11:44 PM (in response to pmuir)It strikes me that we have this because we have unit testing creep going on. If you instead consider that what you want to test is TaskManager integration with the persistence layer, then you wouldn't want to put your TX logic into the test anyway.
Given that people can use TXs in a test (as you show), I think that is sufficient.
After having written some JPA Arquillian tests, I'm now agree that using non-contextual injection into the test case (as opposed to making the test class a bean) is the right way to go.
My thinking about the interceptors on tests originated from automatic transaction begin/rollback in Spring tests. However, I recognize that that's a leaky abstraction and it's much more powerful to work with an injected user transaction object.
-
8. Re: Test class as a bean
alrubinger Jun 8, 2010 12:19 AM (in response to dan.j.allen)I also just did some JPA and Tx testing inside ARQ. The technique I eventually settled upon was injecting EJBs to wrap with the desired functionality. For instance in Tx tests I had an EJB I can submit arbitrary Callables to, and it'll invoke "call" within the context of a new Tx. This is great for passing along entities as well, because you can deal with stuff as they're still managed. And then the user doesn't have to explicitly deal with Tx APIs on his/her own.
For instance:
A similar technique is advised in OpenEJB's docs:
http://openejb.apache.org/3.0/testing-transactions-example.html
A rather longwinded response to say: Yep, the test should likely consult a managed object (either a TxManager, EntityManager, or some indirection) than be managed itself in most cases.
Note: Reloaded Arquillian classes are themselves MC beans.
S,
ALR