2

想象下面的课

public class ClassToBeTested{

  private AnotherClass otherClass;

  public void methodToBeTested(){
     otherClass = new AnotherClass();
     String temp = otherClass.someMethod()

    // ...some other code that depends on temp

  }

}

现在,如果methodToBeTested被设计为接受 I 的实例,AnotherClass我可以轻松地创建一个模拟AnotherClass并告诉 Mockito 在someMethod()被调用时返回一个我更喜欢的值。但是,由于上述代码是按照 AFAIK 设计的,因此无法模拟AnotherClass和测试此方法将取决于someMethod()返回的内容。

无论如何我可以测试上面的代码而不依赖于someMethod()使用 Mockito 或任何其他框架返回的内容?

4

4 回答 4

3

如果可用,您可以使用 SpringReflectionTestUtils setField方法:

http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/util/ReflectionTestUtils.html#setField%28java.lang.Object,%20java.lang.String,%20java。 lang.Object%29

如果不使用反射编写你自己的非常简单的,这里有一些信息:

http://www.java2s.com/Code/Java/Reflection/Setprivatefieldvalue.htm

如下所示,您将需要额外的错误处理才能使其正常工作:

public void setField(Object obj, String fieldName, Object value) {
    Field f = obj.getDeclaredField(fieldName);
    f.setAccessible(true);
    f.set(obj, value);
}

然后可以这样调用它:

setField(objUnderTest, "fieldToSet", mockObject); 

编辑

我刚刚注意到您正在方法中实例化它。如果这是绝对必要的,那么您应该遵循 cyroxx 发布的可能重复的链接。虽然这种做法通常是糟糕设计的标志,所以如果你能把它拿出来,我会的。

于 2013-03-14T10:36:32.700 回答
2

按照其他答案中的建议通过反射设置字段将起作用。

但是,如果您经常做这种事情,我会推荐 PowerMock(与 Mockito 一起使用)或 JMockIt 来实现这一点。两者都允许你模拟构造函数、静态变量、最终字段……简而言之,几乎任何东西。对遗留代码非常有用。

但是,当您编写新代码时,并且您的类依赖于您希望以这种方式隔离的另一个类时,您应该考虑更改设计,以便将另一个对象传递给您的类,而不是由它。搜索“依赖注入”,你会发现很多......

于 2013-03-14T11:02:01.763 回答
1

作为快速修复,我通常将调用包装到new

protected newAnotherClass() { return new AnotherClass(); }

这样,我可以从单元测试中覆盖这个方法。它很脏但很快:-)

于 2013-03-14T11:04:37.517 回答
0

这是一个JMockit测试,它可以满足您的要求,非常简单:

@Test
public void testTheMethodToBeTested(@Mocked final AnotherClass dep)
{
    new NonStrictExpectations() {{ dep.someMethod(); result = "whatever"; }};

    new ClassToBeTested().methodToBeTested();

    new Verifications() {{
        // verify other calls to `dep`, if applicable...
    }};
}
于 2013-03-14T16:05:01.540 回答