Question

I am writing a TestNG test case in a spring project and use jmockit to mock dependencies. I encounter a problem, that is I cannot use Deencapsulation.setField to set dependency to a spring-managed object contain a @Transactional method, the error is:

No instance field of name "dataLogManager" found in class java.lang.reflect.Proxy

My sample code listed here,

Test case:

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:

@Service
public interface QueueManager {         

    @Transactional
    MessageDTO putDataIntoQueue(MessageDTO message);

}

Anybody knows how to solve this problem? Thank you.

Était-ce utile?

La solution

If what you want to test is some specific class implementing the QueueManager interface, then a solution is simply to instantiate the class directly in the test, rather than using Spring for that.

The reason for the exception is that Spring actually creates a proxy class instance for the queueManager field, intended to decorate the real implementation (the proxy object delegates every method call to another object, which would be an instance of an application class actually implementing the QueueManager interface). The proxy class does not contain a field named "dataLogManager", so that's why Deencapsulation.setField(...) can't find it.

If the first solution I mentioned is not applicable, you can still let Spring do the instantiation, provided it also inject the fields inside the queueManager object. To mock the class implementing DataLogManager (and other interfaces), use @Capturing instead of (or in addition to) @Mocked; this will instruct JMockit to extend mocking to all implementation classes.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top