Jersey - How to Mock Service

Jersey - How to mock a service

You need to tell Jersey about your providers. It's failing because the DI framework (HK2) isn't aware of your mock factories and so doesn't know how to inject the dependencies which your resource class needs. You need to tell HK2 about your mock factories.

JerseyTest provides you with a setup hook for just this sort of thing - the configure() method. So, in your test class you need something like this...

@Override
protected Application configure() {
return new ResourceConfig() {
{
register(MockSuccessTokenService.class);
...
}
};
}

That should configure JerseyTest to use your providers when it needs to inject dependencies.

Mock Service inside resource using jersey test framwork

For the service, it's good practice to either inject through the constructor or setter. This makes it easy to mock and pass in during unit testing. As for the mocking, you should use a framework like Mockito. Then you can do stuff like

MyService service = Mockito.mock(MyService.class);
when(service.getObject()).thenReturn(new Object());

HttpHeaders headers = Mockito.mock(HttpHeaders.class);
when(headers.getHeaderString("X-Header")).thenReturn("blah");

UriInfo uriInfo = Mockito.mock(UriInfo.class);
when(uriInfo.getRequestUri()).thenReturn(URI.create("http://localhost"));

Then you can just pass all these mocks to your resource class when UNIT testing.

For INTEGRATION testing you won't need to mock the headers or uriinfo. The actual ones will get passed in. But you can still mock the service if you want. Here's an example

public class MockServiceTest extends JerseyTest  {

public static interface Service {
String getMessage(String name);
}

@Path("message")
public static class MessageResource {

private final Service service;

public MessageResource(Service service) {
this.service = service;
}

@GET
public String get(@QueryParam("name") String name,
@Context HttpHeaders headers,
@Context UriInfo uriInfo) {
String nameQuery = uriInfo.getQueryParameters().getFirst("name");
String header = headers.getHeaderString("X-Header");
assertNotNull(nameQuery);
assertNotNull(header);
return service.getMessage(name);
}
}

private Service service;

@Override
public ResourceConfig configure() {
service = Mockito.mock(Service.class);
return new ResourceConfig().register(new MessageResource(service));
}

@Test
public void testIt() {
Mockito.when(service.getMessage("peeskillet")).thenReturn("Hello peeskillet");

Response response = target("message").queryParam("name", "peeskillet").request()
.header("X-Header", "blah")
.get();
assertEquals(200, response.getStatus());
assertEquals("Hello peeskillet", response.readEntity(String.class));
}
}

How to test a Jersey rest service using mock objects

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.

Mockito with Jersey Test and JAX-RS - UnsatisfiedDependencyException

The MockitoJUnitRunner is for unit tests and JerseyTest is for integration tests.

When using Mockito, your tests will call directly the declared myRestService and Mockito dependency injection will take place.

When using JerseyTest, a new web container is created and your tests talk to MyRestService via an HTTP call. Inside this container, the real dependency injection is happening, the classes are not even seeing you declared mocks.

You can use JerseyTest and Mockito together, exactly as you did. It just requires some extra configurations (as you already found) and the @RunWith annotation is not necessary.

Mocking EJB's with Mockito and Jersey Test Framework

I didn't really give the best example. Though, Lars Juel Jensen's answer uses TestNG, and not JUnit, the set up it much cleaner and provides for better testability

Here's what you can do. As juherr mentioned, the ApplicationServices are different instances. What you can do instead, is forget the Factory altogether. Just use the mocked field

@Mock
private ApplicationService applicationService;

@Override
protected Application configure() {
MockitoAnnotations.initMocks(this);
...
}

Then forget the AbstractBinder. The reason is that it only works for annotations it knows (i.e. it doesn't know @EJB), unless you create some other components to make the annotation know (but that is too much). So just use your setter to inject it

StatsResource resource = new StatsResource(applicationService);
config.register(resource);

Now in each @Test case, you can provide a completely different mock implementation, meaning your wheh(..).then(..)s can be different for each test case. It's more flexible than keeping the same implementation in the factory anyway.

So in your @Test methods, just work off the test class' applicationService.

how to mock sun jersey client post calls?

Here is how I used mocked it

@Mock
Client client;

@Mock
WebResource webResource;

@Mock
WebResource.Builder builder;

@Test
public void test() {
ReflectionTestUtils.setField(payeezyHandler,"webServiceClient",client);
Mockito.when(client.resource(anyString())).thenReturn(webResource);
Mockito.when(webResource.getRequestBuilder()).thenReturn(builder);

Mockito.when(builder.type(MediaType.APPLICATION_JSON_TYPE)).thenReturn(builder);
Mockito.when(builder.accept(MediaType.APPLICATION_JSON_TYPE)).thenReturn(builder);
Mockito.when(builder.post(Matchers.eq(String.class),anyString())).thenReturn(fakeResponse());
}

I know that ReflectionTestUtils are bad to use. But if your test class has just one public function to test, then I guess there is no harm.



Related Topics



Leave a reply



Submit