dev@jersey.java.net

Re: [Jersey] Spring unit testing with Jersey test framework?

From: James Russo <jr_at_halo3.net>
Date: Mon, 24 May 2010 08:25:37 -0400

Hello Paul,

        Thanks. I think that mocking objects is a great tool for independently testing classes while removing the dependencies. My specific goal was to test a request filter which verifies the validity of a header containing a cryptographically signed token used to secure access to a restful API. The filter needs access to a public key to verify the signature and this public key is obtained from a class which that implements the EndpointConfigurationDAO interface. This interface has a getConfiguration method which returns an EndpointConfiguration object. I'm using EasyMock to mock-up this interface and return the configuration object containing the public key. This filter was previously a servlet filter, which I tested by calling the doFilter method using some Mock httpRequest and httpResponse objects from the spring framework, but nothing like that exists in Jersey so this wasn't possible. I looked into mocking up a ContainerRequest object, but I didn't get very far.

I spent some more time on it this weekend and I now have a workable solution and while It may not be very elegant it works. Here is how I accomplished it. I'm open for any suggestions from others on how I might be able to improve it.

First, I use applicationContext to create my mock object by using the following bean definition:

        <bean id="EndpointConfigurationDAO" class="org.easymock.EasyMock"
                factory-method="createMock" lazy-init="false" autowire="byName">
                <constructor-arg index="0"
                        value="net.halo3.ipms.endpoint.dao.EndpointConfigurationDao" />
        </bean>

This will create a EasyMock object implementing the EndpointConfigurationDAO interface. The problem is getting this Mock object into my actual unit test (after JerseyTest creates the applicationContext) so I can use it in the individual test methods. So I basically needed access to the applicationContext which was created by the JerseyTest framework. To make this happen I created another simple class and bean definition:

<bean id="applicationContextHolder" class="net.halo3.ipms.endpoint.security.SpringContextHolder" />

The SpringContextHolder is a simple class which implements the ApplicationContextAware interface so that it will be provided the applicationContext once it is created. I store this ApplicationContext in a static class variable that I can then access from the JUnit test. Using this applicationContext I can obtain my mocked object and work on it.

                EndpointConfigurationDao dao = (EndpointConfigurationDao) SpringContextHolder.applicationContext
                                .getBean("EndpointConfigurationDAO");

and then work with it via EasyMock methods. (ie: EasyMock.expect(dao.getEndpointConfiguration()).andReturn(new EndpointConfiguration());

Hopefully this makes sense to everyone. Like I mention, my main problem was getting access to an object created by the applicationContext which was created by the JerseyTest class. Another solution would have been to create a concrete "test" object which implemented the EndpointConfigurationDAO interface and use static methods to set the EndpointConfiguration object returned. Having this test object wired up in the applicationContext. However, I think that would be practical only in this simple case. If you have a more complex interaction using a mocking framework is the way to go so that you keep the operation of the object under test and its interactions with dependencies in the same junit method.

Take care,

-jr
        

On May 24, 2010, at 5:00 AM, Paul Sandoz wrote:

> Hi James,
>
> I am skeptical of the value of using Mocking techniques for testing, plus i am not all that familiar with specifics of say EasyMock.
>
> The approach we have encouraged is to utilize an embedded solution like Grizzly and then the unit tests become more like functional tests.
>
> However, currently in Jersey it is hard to override Jersey/JAX-RS-related injected dependencies unless you directly instantiate the class you want to test and perform the injection yourself, which is easier if you are using constructor injection, but becomes harder if another DI framework is utilized.
>
> If you can explain what you want to do with code i might be able to help more. Also if there are other developers interested in using mocking and have more experience maybe we can work together to come up with a solution?
>
> Paul.
>
>
> On May 23, 2010, at 12:53 AM, James Russo wrote:
>
>> Hello,
>>
>> I'm looking to test some Jersey Resources which also have some @Autowired dependencies. I'd like to use the Jersey Test framework and something like EasyMock. However in my trying to get this to work I'm not sure how it is possibles since one context will belong to Grizzly and one context will belong to the unit test being run? I need access to the mock objects in the unit test to define the order of methods and return data, and then the same mock object in the resource object so it can call those methods?
>>
>> Is this even possible? Seem like I would need to both use something like SpringJUnit4ClassRunning as well as passing the context to the WebAppDescriptor in JerseyTest class.
>>
>> Thanks,
>>
>> -jr
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: dev-help_at_jersey.dev.java.net
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: dev-help_at_jersey.dev.java.net
>