Какой вопрос?
Ниже приведен тестируемый класс, который, как ожидается, будет протестирован.TestService
изtest
метод, но по какой-то причине (т.doSomething
) не может быть просто выполнено.
так что надеюсьtest
метод действительно выполняется, но дляdoSomething
метод укладки.
package com.example.demo.service;
import com.example.demo.repositroy.TestRepository;
import org.springframework.stereotype.Component;
@Component
public class TestService {
private final TestRepository testRepository;
public TestService(TestRepository testRepository) {
this.testRepository = testRepository;
}
public String doSomething(){
//假装有复杂的无法执行的业务逻辑
testRepository.doSomething();
throw new RuntimeException();
}
public String test() {
doSomething();
//其他逻辑
return "id";
}
}
Как решить?
Использование мокбинов
Если только использовать@MockBean
Смоделируйте измененный объект, чтобыTestService
изdoSomething()
метод больше не выполняет конкретные детали, ноMockBean
будет издеваться над всеми методами целевого объекта, поэтомуtest
Это не может быть реализовано, и это не может быть протестировано.
а такжеwhen...thenCallRealMethod
Некоторых имитационных эффектов можно добиться, толькоtest
Метод действительно выполняется.
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestServiceTest {
@MockBean
TestService testService;
@Test
public void test(){
when(testService.test()).thenCallRealMethod();
assertThat(testService.test(), equalTo("id"));
}
}
Использование SpyBeans
использовать@SpyBean
декоративныйtestService
является реальным объектом, только еслиdoReturn("").when(testService).doSomething()
час,doSomething
Метод заглушен, и другие методы по-прежнему вызываются.
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestServiceTest {
@SpyBean
TestService testService;
@Test
public void test(){
doReturn("").when(testService).doSomething();
assertThat(testService.test(), equalTo("id"));
}
}
маленькая ловушка
и использовать@MockBean
Другой, названный в предыдущем разделеdoReturn("").when(testService).doSomething()
ВремяdoSomething
Метод забит. а такжеwhen(testService.doSomething()).thenReturn("")
Этот эффект не может быть достигнут. Причина: использование@SpyBean
декоративныйtestService
является реальным объектом, поэтомуtestService.doSomething()
на самом деле будет называться.
В официальной документации Mockito говорится следующее:
Sometimes it's impossible or impractical to use when(Object) for stubbing spies. Therefore when using spies please consider doReturn|Answer|Throw() family of methods for stubbing. Example:
List list = new LinkedList();
List spy = spy(list);
//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
Mockito does not delegate calls to the passed real instance, instead it actually creates a copy of it. So if you keep the real instance and interact with it, don't expect the spied to be aware of those interaction and their effect on real instance state. The corollary is that when an unstubbed method is called on the spy but not on the real instance, you won't see any effects on the real instance.
Watch out for final methods. Mockito doesn't mock final methods so the bottom line is: when you spy on real objects + you try to stub a final method = trouble. Also you won't be able to verify those method as well.
Резюме:
- При использовании шпиона рассмотрите возможность использования
doReturn|Answer|Throw()
- Для переменных, измененных шпионом, Mockito воссоздает копию экземпляра и не воздействует напрямую на реальный экземпляр.
- шпион не влияет на окончательные методы
SpyBean vs MockBean
SpyBean
а такжеMockBean
даspring-boot-test
Две аннотации, предоставляемые пакетом для экземпляров, управляемых контейнером Spy или Mock Spring. Spy и Mock как раз наоборот: по умолчанию все методы spy вызываются на самом деле, а все методы Mock по умолчанию вызывают реализацию mock.
В чем разница в сценариях использования? Основываясь на приведенном выше примере, хотя оба могут быть достигнуты,SpyBean
более подходящим, так как приведенный выше пример является проверкойTestService
,такtestService
Не должен быть полностью издевательским экземпляром. и если вTestService
Хотите издеваться над испытательной силойTestRepository
,использоватьMockBean
является более подходящим.
Рассмотрите возможность использования заглушек для раздела класса тестового тела.
SpyBean
, накапливая внешние зависимости, рассмотрите возможность использованияMockBean
.
Суммировать
-
SpyBean
а такжеMockBean
даspring-boot-test
Две аннотации, предоставляемые пакетом, используются для экземпляров, управляемых контейнером Spy или Mock Spring; - использовать
SpyBean
илиSpy
Когда требуется нагромождение метода, необходимо обратить внимание на некоторые ограничения использования; - Рассмотрите возможность использования заглушек для раздела класса тестового тела.
SpyBean
, накапливая внешние зависимости, рассмотрите возможность использованияMockBean
.