Как внедрить объект 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 3

1 ответ:

Если вы хотите протестировать какой-то конкретный класс, реализующий интерфейс QueueManager, то решение состоит в том, чтобы просто создать экземпляр класса непосредственно в тесте, а не использовать для этого Spring.

Причина исключения заключается в том, что Spring фактически создает экземпляр класса proxy для Поля queueManager, предназначенного для украшения реальной реализации (объект proxy делегирует каждый вызов метода другому объекту, который был бы экземпляром класса приложения на самом деле реализация интерфейса QueueManager). Прокси-класс не содержит поля с именем "dataLogManager", поэтому Deencapsulation.setField(...) не может его найти.

Если первое решение, которое я упомянул, неприменимо, вы все равно можете позволить Spring выполнить создание экземпляра, при условии, что он также вводит поля внутри объекта queueManager. Чтобы издеваться над классом, реализующим DataLogManager (и другие интерфейсы), используйте @Capturing вместо (или в дополнение к) @Mocked; это даст команду JMockit распространить издевательство на все классы реализации.