模拟方法作为另一个方法的参数

Mock method as parameter another method

我在测试调用具体方法(Operation 实例中的 IFunction)的次数时遇到问题。

根据:

  1. http://easymock.org/user-guide.html#mocking-annotations

  2. http://www.ibm.com/developerworks/library/j-easymock/

  3. How to use EasyMock expect

我写了一些东西:

class Operation{
   public double[] calculateSth(IFunction function, int [] t){
      for(int i=0 ; i<5 ; i+=1)
          function(t, new int[]{1,2,3});

   return new double[]{1,2,3};
   }

}

interface IFunction{
   double f(int[] a, int[]b);
}

class ConcreteF implements IFunction{
   double f(int[]a, int[]b){
       return 5;
   }
}

还有我的测试课: @考试科目 运算;

@Mock
IFunction function;

@Before
public void setUp() throws Sth{
    op=new Operation();
    function = EasyMock.createMock(IFunction.class);
}

@Test
public void howManyTimes(){


    EasyMock.expect(function.f(EasyMock.notNull(), EasyMock.notNull())
                   )
    .andReturn((double)EasyMock.anyDouble()).times(3);


    EasyMock.replay(function);

    op.calculateSth(function, new double[]{0,0,0});

    //verify
    EasyMock.verify(function);

}

结果: java.lang.NullPointerException

at org.easymock.internal.Injector.injectMocks(Injector.java:80)
at org.easymock.EasyMockSupport.injectMocks(EasyMockSupport.java:624)
at org.easymock.EasyMockRunner.withBefores(EasyMockRunner.java:50)

这是我第一次使用 easymock,我不知道如何修复它;/

我会回答这个问题,而不会详细讨论原始方法是否有用(代码甚至无法编译),更不用说测试方法了。

@TestSubject Operation op;

这条线是可疑的。我意识到您正在 @Before 注释的 setUp 方法中实例化它,但看起来 Easymock 试图在它之前注入模拟(用 @Mock 注释的模拟)做任何事情(并且可以理解)并爆炸,因为那时参考是 null

v3.2 中引入的注释支持也被视为消除对 setUp 方法的需要的一种方式。但是您似乎将两者混合使用并错误地使用了它。选择其中之一 - 我建议您使用注释。

引用 Easymock user guide(本用户指南非常好,因此请务必在使用该库之前阅读此内容),

@RunWith(EasyMockRunner.class) 
public class ExampleTest {

  @TestSubject 
  private ClassUnderTest classUnderTest = new ClassUnderTest(); // 2 

  @Mock 
  private Collaborator mock; // 1 

  @Test 
  public void testRemoveNonExistingDocument() { 
    replay(mock); 
    classUnderTest.removeDocument("Does not exist"); 
  } 
}

The mock is instantiated by the runner at step 1. It is then set by the runner, to the listener field on step 2. The setUp method can be removed since all the initialization was done by the runner.