Использование @Spy и @Autowired вместе

У меня есть класс обслуживания с 3 методами, класс обслуживания также использует некоторые аннотации @Autowired. Из трех методов я хочу смоделировать два метода, но использую реальный метод для третьего.

Проблема в следующем:

  1. Если я использую @Autowired с @Spy, вызывается реализация всех трех реальных методов.
  2. Если я использую только @Spy, вызов реального метода возвращается с указателем Null, поскольку инициализация объектов Autowired отсутствует.

5 ответов

Я знаю об этих двух вариантах:

  1. Используйте аннотацию @SpyBean из spring-boot-test как единственную аннотацию
@Autowired
@InjectMocks
private ProductController productController;

@SpyBean
private ProductService productServiceSpy;
  1. Использовать отражение Java для "автоматического подключения" шпионского объекта, например, ReflectionTestUtils
@Autowired
private ProductController productController;

@Autowired
private ProductService productService;

@Before
public void setUp() {
    ProductService productServiceSpy = Mockito.spy(productService);
    ReflectionTestUtils.setField(productController, "productService", productServiceSpy);
}

Я сам был удивлен, но это работает для нас. У нас есть много мест, таких как:

@Spy
@Autowired
private FeatureService featureService;

Я думаю, я знаю, почему вы столкнулись с этой проблемой. Дело не в инъекциях, а в when(bloMock.doSomeStuff()).thenReturn(1) против doReturn(1).when(bloMock).doSomeStuff(), Смотрите: http://www.stevenschwenke.de/spyingWithMockito

Очень важное различие заключается в том, что первый параметр будет вызывать метод doSomeStuff(), а второй - нет. И то и другое заставит doSomeStuff() вернуть желаемый 1.

Using @Spy together with @Autowired works until you want to verify interaction between that spy and a different component that spy is injected into. What I found to work for me was the following approach found at https://dzone.com/articles/how-to-mock-spring-bean-version-2

@Configuration
public class AddressServiceTestConfiguration {
    @Bean
    @Primary
    public AddressService addressServiceSpy(AddressService addressService) {
        return Mockito.spy(addressService);
    }
}

This turns your autowired component into a spy object, which will be used by your service and can be verified in your tests.

У меня похожая проблема, и мы исправили ее с помощью @SpyBean и @Autowired вместе:

        @SpyBean
  @Autowired
  ClosedInvoiceEventHandler closedInvoiceEventHandler;

ОБНОВЛЕНИЕ 20220509-203459

Для пользователя TestNg добавьте это в тестовый класс

@TestExecutionListeners(слушатели = MockitoTestExecutionListener.class)

и расширяет AbstractTransactionalTestNGSpringContextTests

тогда @SpyBean будет работать.


даются два варианта В этом ответе

Однако я столкнулся с проблемами.

  1. Используйте аннотацию @SpyBean из spring-boot-test в качестве единственной аннотации

Это кажется хорошей идеей, но только для пользователей junit. Я использую TestNg в своих тестах. Я не нашел способа заставить @SpyBean хорошо работать с TestNg.

  1. Используйте отражение Java для «автоподключения» шпионского объекта, например ReflectionTestUtils.

Кажется, что у всех bean-компонентов есть окончательные методы, потому что Spring уже проксирует их и делает методы окончательными. Таким образом, Mockito.spy может быть невозможен с автоматическим подключением bean-компонента.

Действительно, я попытался и получил исключение:

недопустимое использование сопоставителей аргументов Ожидается 0 совпадений 1 записано

Я сам не нашел причину, но я видел объяснение отсюда

Итак, остался единственный подход: /questions/3917983/ispolzovanie-spy-i-autowired-vmeste/55143842#55143842

Я не уверен, что это работает, я попробую.-- пробовал, не работает. возможно, потому что параметр метода также является прокси-сервером Spring. Методы также являются окончательными.

Другие вопросы по тегам