SteveSt
SteveSt

Reputation: 1297

How to test a Jersey rest service using mock objects

I have developed a rest service using Jersey. Now I want to write some integration tests for this web service but since not every class being used from the web service is already implemented I need to mock some of them. For example I have the following class:

public class A {

    private String getWeather() {
        return null;
    }
}

My web service looks like this :

@Path("/myresource")
public class MyResource {

    @GET 
    @Produces("text/plain")
    public String getIt() {
        A a = new A();
        return a.getWeather();
    }
}

The problem is that the getWeather function is not ready so I need to mock the return value for this function. But for the integration test where I issue a rest call I don't know how to do that.

Are there any ideas?

Upvotes: 1

Views: 4359

Answers (2)

froderik
froderik

Reputation: 4808

To make your design decoupled from A you should pass it in as a parameter to MyResource. Then you can easily mock it by hand or with mockito. With constructor injection it would look like this:

@Path("/myresource")
public class MyResource {

    private A a;

    public MyResource(A a) {
        this.a = a;
    }

    @GET 
    @Produces("text/plain")
    public String getIt() {
        return a.getWeather();
    }
}

and you can test it with

@Test
public void shouldGetIt() {
    A a = mock(A.class);
    when(a.getWeather()).thenReturn("sunny!");

    MyResource r = new MyResource(a);
    assertThat(r.getIt(), is("sunny!));
}

This makes your design decoupled. MyResource no longer depends on A directly but on anything that looks lik an A. Another benefit is that mockito doesn't mess with you class files. It is your code that is tested - not something that has been generated on the fly.

Many consider injection by constructor to be a bit old school. I am old so I like it.... With spring (a framework I don't recommend that you pick up) you can autowire variables like so:

@Autowire
private A a;

and you don't need the constructor at all. Spring will find a the only implementation of A and insert it in this variable. I prefer explicit programming so I would chose constructor injection any day.

Upvotes: 3

Pat
Pat

Reputation: 2258

You may be able to achieve this using Power Mockito (https://code.google.com/p/powermock/wiki/MockitoUsage)

@RunWith(PowerMockRunner.class)
@PrepareForTest({ MyResource.class })
public class MyResourceTest {

   @Test
   public void testGetIt()() {
     MyResource mr = new MyResource();

     //Setup mock
     A mockA = PowerMockito.mock(A.class);

     String mockReturn = "Some String";

     //Stub new A() with your mock
     PowerMockito.whenNew(A.class).withAnyArguments().thenReturn(mockA);
     PowerMockito.doReturn(mockReturn).when(mockA).getWeather();
     String ret = mr.getIt();

     //asserts go here
   }
}

Note that you can mock a local variable creation using PowerMockito's whenNew - this should take care of your concern for A a = new A() code in getIt() method.

Upvotes: 2

Related Questions