Я разработал сервис отдыха с использованием Джерси. Теперь я хочу написать некоторые интеграционные тесты для этого веб-сервиса, но так как не каждый класс, используемый из веб-службы, уже реализован, мне нужно издеваться над некоторыми из них. Например, у меня есть следующий класс:
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 не готова, поэтому мне нужно высмеять возвращаемое значение для этой функции. Но для теста интеграции, в котором я делаю вызов для отдыха, я не знаю, как это сделать.
Есть идеи?
Вы можете достичь этого, используя 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
}
}
Обратите внимание, что вы можете издеваться над созданием локальной переменной с помощью PowerMockito whenNew
- это должно позаботиться о вашей проблеме для A a = new A()
кода A a = new A()
в getIt()
.
Чтобы разделить дизайн на A, вы должны передать его в качестве параметра MyResource. Тогда вы можете легко издеваться над ним вручную или с помощью mockito. При инсталляции конструктора это будет выглядеть так:
@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 и вставляет ее в эту переменную. Я предпочитаю явное программирование, поэтому я бы выбрал конструкторную инъекцию в любой день.
getWeather
вызовgetWeather
и вернуть объектtest string
для тестов. Посмотрите code.google.com/p/mockito