我正在Spring项目中编写一个TestNG测试用例,并使用jmockit来模拟依赖项。我遇到一个问题,就是我无法使用Deencapsulation.setField来设置对包含@Transactional方法的spring-managed对象的依赖,错误是:
在类java.lang.reflect.Proxy
中找不到名称“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);
}
有谁知道如何解决这个问题?谢谢。
答案 0 :(得分:1)
如果您要测试的是一些实现QueueManager
接口的特定类,那么解决方案就是直接在测试中实例化该类,而不是使用Spring。
异常的原因是Spring实际上为queueManager
字段创建了一个代理类实例,用于修饰实际实现(代理对象将每个方法调用委托给另一个对象) ,这将是实际实现QueueManager
接口的应用程序类的实例。代理类不包含名为" dataLogManager"的字段,因此Deencapsulation.setField(...)
无法找到它。
如果我提到的第一个解决方案不适用,你仍然可以让Spring进行实例化,前提是它还会在queueManager
对象中注入字段。要模拟实现DataLogManager
(和其他接口)的类,请使用@Capturing
代替@Mocked
(或除此之外){{1}};这将指示JMockit将模拟扩展到所有实现类。