Java 如何模拟DefaultMessageListenerContainer
我正在努力模拟(使用Mockito)DefaultMessageListenerContainer(Java 如何模拟DefaultMessageListenerContainer,java,spring,mocking,mockito,Java,Spring,Mocking,Mockito,我正在努力模拟(使用Mockito)DefaultMessageListenerContainer(org.springframework.jms.listener.DefaultMessageListenerContainer)。这是我的密码: @Mock private DefaultMessageListenerContainer defaultMessageListenerContainer; @Before public void init() { MockitoAnnot
org.springframework.jms.listener.DefaultMessageListenerContainer
)。这是我的密码:
@Mock
private DefaultMessageListenerContainer defaultMessageListenerContainer;
@Before
public void init() {
MockitoAnnotations.initMocks( this );
incomingFeedController = new IncomingFeedControllerImpl();
}
@Test
public void testHandleConnectionState() {
List< DefaultMessageListenerContainer > listeners =
new ArrayList< DefaultMessageListenerContainer >();
listeners.add( defaultMessageListenerContainer );
incomingFeedController.setContainers( listeners );
when( defaultMessageListenerContainer.isRunning() ).thenReturn( false );
}
但在junit运行之后,这一行将以:
java.lang.NullPointerException
at org.springframework.jms.listener.AbstractJmsListeningContainer.isRunning(AbstractJmsListeningContainer.java:312)
at com.source.etf.manager.integrationgateway.feedcontroller.IncomingFeedControllerTest.testHandleConnectionState(IncomingFeedControllerTest.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
我发现lifecycleMonitor
对象没有被实例化。此对象在顶部的AbstractJMSListingContainer
中声明:
protected final Object lifecycleMonitor = new Object();
您知道如何正确模拟
DefaultMessageListenerContainer
?您仍然需要在正在初始化的对象上设置模拟
我看到您正在测试IncomingFeedControllerImpl,您的模拟对象很可能是此类实例的成员。因为您没有在IncomingFeedControllerImpl
上显式设置模拟的DefaultMessageListenerContainer
,所以AbstractJMSleintingContainer
(可能是@Autowired
)仍在挂起,没有被模拟
您需要使用setter方法或构造函数来注入它。(您也可以
@Autowired
it)Mockito不能模拟final类或final方法。这些约束由JVM本身强制执行。模拟这样的代码需要重写类字节码并将其加载到另一个类加载器中。这导致了非常复杂的代码;PowerMock朝着这个方向发展,代码很难维护
另外,不要模仿你不拥有的类型,请参阅上的4-5个第一个结果。为什么需要在单元测试中模拟弹簧类型。您应该创建一些间接方法来避免Spring遵从性,或者编写集成测试;后者似乎更合适,因为它与JMS相关。您需要使用PowerMock,或者按照@Brice的建议进行集成测试。以下是如何在PowerMock中执行此操作:
@RunWith(PowerMockRunner.class)
@PrepareForTest(DefaultMessageListenerContainer.class)
public class MyTestClass {
// cannot use the @Mock annotation
private DefaultMessageListenerContainer defaultMessageListenerContainer;
@Before
public void init() {
// This should allow the mocking of final methods as well.
defaultMessageListenerContainer =
PowerMockito.mock(DefaultMessageListenerContainer.class);
incomingFeedController = new IncomingFeedControllerImpl();
}
@Test
public void testHandleConnectionState() {
List< DefaultMessageListenerContainer > listeners =
new ArrayList< DefaultMessageListenerContainer >();
listeners.add( defaultMessageListenerContainer );
incomingFeedController.setContainers( listeners );
when( defaultMessageListenerContainer.isRunning() ).thenReturn( false );
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest(DefaultMessageListenerContainer.class)
公共类MyTestClass{
//无法使用@Mock注释
私有DefaultMessageListenerContainer DefaultMessageListenerContainer;
@以前
公共void init(){
//这也应该允许模拟最终方法。
defaultMessageListenerContainer=
mock(DefaultMessageListenerContainer.class);
incomingFeedController=新的IncomingFeedControllerImpl();
}
@试验
public void testHandleConnectionState(){
列表侦听器=
新建ArrayList();
添加(defaultMessageListenerContainer);
输入FeedController.setContainers(侦听器);
当(defaultMessageListenerContainer.isRunning())。然后返回(false);
}
}
类似的问题:为什么要模拟它?您的代码不应该依赖于DefaultMessageListenerContainer
,它是一个Spring基础结构组件。事实并非如此。已经试过了。这肯定与未实例化此lifecycleMonitor有关。好吧,根据您的代码,您正试图模拟您的DefaultMessageListenerContainer
,并通过接收AbstractJMSleintingContainer
,这意味着从未在您的IncomingFeedController
上设置模拟对象。我只是复制了此部分,但这是我的测试代码:@test public void testHandleConnectionState(){Listlisteners=new ArrayList();listeners.add(defaultMessageListenerContainer);incomingFeedController.setContainers(侦听器);when(defaultMessageListenerContainer.isRunning())。然后返回(false);
编辑您的问题并添加测试。是的@PrepareForTest
指令是强制性的,否则PowerMock不会在临时PowerMock类加载器的域中准备此类
protected final Object lifecycleMonitor = new Object();
@RunWith(PowerMockRunner.class)
@PrepareForTest(DefaultMessageListenerContainer.class)
public class MyTestClass {
// cannot use the @Mock annotation
private DefaultMessageListenerContainer defaultMessageListenerContainer;
@Before
public void init() {
// This should allow the mocking of final methods as well.
defaultMessageListenerContainer =
PowerMockito.mock(DefaultMessageListenerContainer.class);
incomingFeedController = new IncomingFeedControllerImpl();
}
@Test
public void testHandleConnectionState() {
List< DefaultMessageListenerContainer > listeners =
new ArrayList< DefaultMessageListenerContainer >();
listeners.add( defaultMessageListenerContainer );
incomingFeedController.setContainers( listeners );
when( defaultMessageListenerContainer.isRunning() ).thenReturn( false );
}
}
private DefaultMessageListenerContainer createFailingContainer() {
DefaultMessageListenerContainer container = new DefaultMessageListenerContainer() {
@Override
public void start() throws JmsException {
throw new MyJmsException("TEST");
}
@Override
public void stop() throws JmsException {
throw new MyJmsException("TEST");
}
};
return container;
}
class MyJmsException extends JmsException {
private static final long serialVersionUID = 1L;
public MyJmsException(String msg) {
super(msg);
}
}