Отражение в нескольких обернутых объектах - PullRequest
0 голосов
/ 04 ноября 2011

В тесте JUnit я хочу изменить шаблон спящего режима в Spring DAO. Это DAO

  1. с аннотацией @Transactional, поэтому она переносится во время выполнения и
  2. шпионил за Mockitos spy () - метод. Таким образом, шпион во второй раз закроет DAO.

Таким образом, в DAO теперь есть два объекта-обертки: один от @Transactional, другой от шпиона. Из-за того, что неизвестно, какая из этих оболочек создана первой, я не могу установить шаблон спящего режима в DAO с помощью отражения.

Как мне установить шаблон в двойном DAO?

[Изменить]

Некоторые Источник:

/**
* This class gets wrapped by a proxy object because of @Transactional.
*/
@Transactional 
public class MyDao implements SomeDaoInterface { ... }

В тестовом классе:

public class MyTestClass {
@Autowired 
private MyDao myDao;

@Test
public void myTestMethod() throws Exception {
   final MyDao daoSpy = spy(myDao);   // Dao gets wrapped with second wrapper

   final Field field = MyDao.class.getDeclaredField("template");
   field.setAccessible(true);
   field.set(daoSpy, mySpecialMockedTemplate);  // ERROR: want to inject the template but
                                                // dont know in which wrapper
}
}

Ответы [ 2 ]

2 голосов
/ 04 ноября 2011

Похоже, ваш код отражения неверен. Используйте это утверждение вместо:

field.set(daoSpy, mySpecialMockedTemplate);

Однако, глядя на ваш тестовый код, кажется, что вы используете Spring для создания экземпляра MyDao. Кажется странным использовать отражение для установки шаблона, почему бы не настроить его в Spring? Или даже использовать реальный сеттер? Или сделайте поле защищенным, чтобы к нему мог получить доступ только тестовый модуль.

РЕДАКТИРОВАТЬ: Что касается инъекции, вы можете создать экземпляр DAO в вашем тесте и сделать ваш specialMockedTemplate инъекцией Mockito. Вы могли бы написать что-то вроде:

@RunWith(MockitoJUnitRunner.class)
public class MyTestClass {
    @InjectMocks private MyDao dao;

    @Mock SpecialTemplate specialTemplate;

    @Test void dao_should_call_the_template_with_parameter_A_and_B() {
        // given

        // when
        dao.someCall("A", "B");

        // then
        verify(specialTemplate).someCallWith("A", "B");
    }
}

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

2 голосов
/ 04 ноября 2011

Вызовите метод установки вместо доступа к полю.

...