如何使用模拟对象测试Jersey休息服务

时间:2014-08-03 11:05:53

标签: java rest mocking jersey integration-testing

我使用泽西岛开发了休息服务。现在我想为这个Web服务编写一些集成测试,但由于并非所有从Web服务中使用的类都已经实现,我需要模拟它们中的一些。例如,我有以下类:

public class A {

    private String getWeather() {
        return null;
    }
}

我的网络服务如下:

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

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

问题是getWeather函数没有准备好所以我需要模拟这个函数的返回值。但对于我发出休息呼叫的集成测试,我不知道该怎么做。

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

要使您的设计与A分离,您应该将其作为参数传递给MyResource。然后你可以轻松地用手或模拟它来模拟它。使用构造函数注入时,它看起来像这样:

@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();
    }
}

您可以使用

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

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

这使您的设计脱钩。 MyResource不再直接依赖于A,而是依赖于任何看起来像A的东西。另一个好处是mockito不会弄乱你的类文件。这是您的代码经过测试 - 而不是即时生成的代码。

许多人认为建设者注射有点旧学校。我老了所以我喜欢它....随着春天(我不建议你选择一个框架),你可以像这样自动装配变量:

@Autowire
private A a;

你根本不需要构造函数。 Spring将找到A的唯一实现并将其插入此变量中。我更喜欢显式编程,所以我会在任何一天选择构造函数注入。

答案 1 :(得分:2)

您可以使用Power Mockitohttps://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
   }
}

请注意,您可以使用PowerMockito的whenNew模拟本地变量创建 - 这应该照顾您对A a = new A()方法中getIt()代码的关注。