Java 如何使用EasyMock从模拟接口调用方法

Java 如何使用EasyMock从模拟接口调用方法,java,unit-testing,junit,easymock,Java,Unit Testing,Junit,Easymock,我正在为一个类编写一个Junit测试,在下面一行中得到一个java.lang.NullPointerException: expect(lineConfigurationHandlerMock.getDeviceControlHandler().getDeviceParameters(item1)).andReturn(myDeviceParameters); 我认为(虽然我不确定)它与我在模拟接口中调用的方法(getDeviceControlHandler)有关。因为我在子标题行之前添加了这

我正在为一个类编写一个Junit测试,在下面一行中得到一个java.lang.NullPointerException:

expect(lineConfigurationHandlerMock.getDeviceControlHandler().getDeviceParameters(item1)).andReturn(myDeviceParameters);
我认为(虽然我不确定)它与我在模拟接口中调用的方法(getDeviceControlHandler)有关。因为我在子标题行之前添加了这行代码:

Assert.assertNotNull(comLineConfigurationHandlerMock.getDeviceControlHandler());
我有以下错误:

java.lang.AssertionError

我被困在这里,真的需要一些帮助

提前谢谢

引发的异常:

java.lang.NullPointerException
at de.myproject.project.classTest.testGetParameters(classTest.java:123)
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.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
以下是笔试:

public class classTest {

// class under test
private classUnderTest classUnderTest;

private LineConfigurationHandler LineConfigurationHandlerMock;

private IMocksControl mocksControl;

List<DeviceParameter> myDeviceParameters;
DeviceParameter deviceParameter1;
DeviceParameter deviceParameter2;

@Before
public void setUp() throws Exception
{
    mocksControl = EasyMock.createControl();

    LineConfigurationHandlerMock = mocksControl.createMock(LineConfigurationHandler.class);

    classUnderTest = new classUnderTest();
    classUnderTest.setLineConfigurationHandler(LineConfigurationHandlerMock);

    String item1 = "item1";

    myDeviceParameters = new ArrayList<DeviceParameter>();
    myDeviceParameters.add(deviceParameter1);
    myDeviceParameters.add(deviceParameter2);

    //Other stuff
}

@Test
public void testGetParameters()
{

    expect(LineConfigurationHandlerMock.getDeviceControlHandler().getDeviceParameters(item1)).andReturn(myDeviceParameters);

    mocksControl.replay();

    //Some code .....
 }
}
DeviceControlHandler.class

public interface DeviceControlHandler extends Serializable{

List<DeviceParameter> getDeviceParameters(String deviceId);

//Other methods  declaration ...
}
public interface DeviceControlHandler扩展可序列化{
列出getDeviceParameters(字符串deviceId);
//其他方法声明。。。
}

这并不简单,但非常确定:

expect(lineConfigurationHandlerMock.getDeviceControlHandler().getDeviceParameters(item1)).andReturn(myDeviceParameters);
该行包含两个可以抛出NPE的项:

A) lineConfigurationHandlerMock-->该对象可以为空

B) .getDeviceControlHandler()-->该方法可以返回NULL

就这样。你可以做一些简单的打印输出,比如

System.out.println("mock: " + lineConfigurationHandlerMock)
System.out.println("handler: " + lineConfigurationHandlerMock.getDeviceControlHandler())
找出哪一个是空的。在您的情况下,我认为您缺少lineConfigurationHandlerMock对象的设置:您必须告诉它在调用getDeviceControlHandler()时返回什么

为了做到这一点,首先必须创建另一个模拟对象,该对象在调用getDeviceControlHandler()时应返回。还有另一个模拟,您必须配置对getDeviceParameters()的调用

换句话说:您不能指定像“mock.getA().doSomething()”—相反,您需要另一个“mockedA”,告诉它“doSomething()”;然后告诉“mock”,getA()应该返回“mockedA”

更新:我不熟悉这些注释;我习惯于使用“裸机模式下的EasyMock”;像


谢谢你的帮助。实际上,我已经完成了打印输出,getDeviceControlHandler()返回NULL。现在我想实施你在回答的最后一段中解释的内容,但我不知道怎么做。你能告诉我如何实施吗?谢谢我的回答;但请理解,我不喜欢使用这些注释;所以你必须从那里开始工作。
expect(lineConfigurationHandlerMock.getDeviceControlHandler().getDeviceParameters(item1)).andReturn(myDeviceParameters);
System.out.println("mock: " + lineConfigurationHandlerMock)
System.out.println("handler: " + lineConfigurationHandlerMock.getDeviceControlHandler())
SomeObject innerMock = EasyMock.createMock(SomeObject);
expect(innerMock.doSomething()).andReturn("who cares");

SomeOther outerMock = EasyMock.createMock(SomeOther);
expect(outerMock.getDeviceControlHandler("sounds familiar")).andReturn(innerMock);