1

我有一个类似于以下的方法:

public void myMethod(MyClass c)
{
  if (c == null)
  {
    return;
  }
  try
  {
    c.someMethod();
  }
  catch (SomeException e)
  {
    // log the exception, possibly re-throw
  }
}

我试图找到一种方法来设置 MyClass 参数 c 的模拟实例,以便它为自己返回 null 值,并且永远不会调用 c.someMethod() 。我的单元测试如下所示:

@Test
public void Test_myMethod_With_Null_MyClass_Does_Not_Call_someMethod()
{
    Mockery mockery = new Mockery()
    {{
            setImposteriser(ClassImposteriser.INSTANCE);
    }};

    final MyClass mockMyClass = mockery.mock(MyClass.class);

    try
    {
        mockery.checking(new Expectations()
        {{
            oneOf(mockMyClass).equals(null);
                will(returnValue(true));

            never(mockMyClass).someMethod();
        }});
    }
    catch (Exception e)
    {
        logger.fatal(e);
        fail("Exception thrown in test.");
    }
    Util.myMethod(mockMyClass);
}

基本上,我正在设置 MyClass 的模拟实例,并对其设置期望,即当针对空值测试其值时,它将返回 true,并且永远不会调用方法 someMethod()。

现在,测试失败了,因为 jMock 说不可能覆盖 Object 类提供的方法(equals(null) 部分)。

有没有办法用 jMock 做到这一点?这种模式有意义吗?这是一个有效的测试吗?如果没有,是否有人对如何测试有任何建议?

4

2 回答 2

3

我认为您不能仅使用 JMock 来测试此代码。

我会通过null直接传入来测试这个。如果没有抛出或记录异常,您就知道您的代码按预期工作。@Test

public void Test_myMethod_With_Null_MyClass_Does_Not_Call_someMethod()
{
    Util.myMethod(null);
    //no exception should be thrown.
}

如果您想让它更明确,您可以将myMethod(null)调用包装在 try/catch 块中,但这不是必需的,除非在失败时阐明失败原因。

public void Test_myMethod_With_Null_MyClass_Does_Not_Call_someMethod()
{
    try
    {
        Util.myMethod(null);
    }
    catch( ExpectedException e )
    {
        fail( "Should not have thrown exception: " + e.getMessage() ); 
    }
}

这是一个足够的测试,因为您知道 if cis nullthenc.something()当然不能被调用。

于 2009-05-10T04:45:32.023 回答
1

模拟应该用于测试对象如何与其协作者交互。如果没有合作者,那么就没有什么可嘲笑的了。传入 null 更简单,更具表现力。

于 2009-05-21T12:18:40.757 回答