Как внедрить объект mocked с помощью jmockit в управляемый объект spring с помощью метода @Transactional?
Я пишу тестовый случай TestNG в проекте spring и использую jmockit для моделирования зависимостей. Я сталкиваюсь с проблемой, которая заключается в том, что я не могу использовать Деэнкапсуляцию.setField чтобы задать зависимость для объекта, управляемого spring, содержащего метод @ Transactional, Ошибка:
В классе java отсутствует поле экземпляра с именем "dataLogManager".яз..отражать.Прокси
Мой пример кода, приведенный здесь,
Тестовый случай:
public class QueueManagerTest extends AbstractTestNGSpringContextTests {
@Autowired
private QueueManager queueManager;
@Autowired
private ApplicationContext context;
@Autowired
private TransInfoManager transInfoManager;
@Autowired
private Generator generator;
@Autowired
private MessageDTOFactoryBean messageDTOFactoryBean;
@Test(description="單元測試:寫入一筆Data資料,非邊界情況下(無待處理筆數)")
public void writeControlMessage(
@Mocked final TransInfoManager transInfoManager,
@Mocked final DataManager dataManager,
@Mocked final DataLogManager dataLogManager
) {
....
Deencapsulation.setField(queueManager, "dataLogManager", dataLogManager);
Deencapsulation.setField(queueManager, "dataManager", dataManager);
Deencapsulation.setField(queueManager, "transInfoManager", transInfoManager);
....
}
}
Обслуживание:
@Service
public interface QueueManager {
@Transactional
MessageDTO putDataIntoQueue(MessageDTO message);
}
Любой знает, как это сделать. решить эту проблему? Спасибо.
1 ответ:
Если вы хотите протестировать какой-то конкретный класс, реализующий интерфейс
QueueManager
, то решение состоит в том, чтобы просто создать экземпляр класса непосредственно в тесте, а не использовать для этого Spring.Причина исключения заключается в том, что Spring фактически создает экземпляр класса proxy для Поля
queueManager
, предназначенного для украшения реальной реализации (объект proxy делегирует каждый вызов метода другому объекту, который был бы экземпляром класса приложения на самом деле реализация интерфейсаQueueManager
). Прокси-класс не содержит поля с именем "dataLogManager", поэтомуDeencapsulation.setField(...)
не может его найти.Если первое решение, которое я упомянул, неприменимо, вы все равно можете позволить Spring выполнить создание экземпляра, при условии, что он также вводит поля внутри объекта
queueManager
. Чтобы издеваться над классом, реализующимDataLogManager
(и другие интерфейсы), используйте@Capturing
вместо (или в дополнение к)@Mocked
; это даст команду JMockit распространить издевательство на все классы реализации.