如何模拟未作为参数传递的对象



想象下面的类

public class ClassToBeTested{
  private AnotherClass otherClass;
  public void methodToBeTested(){
     otherClass = new AnotherClass();
     String temp = otherClass.someMethod()
    // ...some other code that depends on temp
  }
}

现在,如果methodToBeTested被设计为接受AnotherClass的实例,我可以很容易地创建AnotherClass的模拟,并告诉Mockito在调用someMethod()时返回一个我喜欢的值。然而,由于上述代码是AFAIK设计的,因此不可能模拟AnotherClass,并且测试此方法将取决于someMethod()返回的内容。

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

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

http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/util/ReflectionTestUtils.html setField % 28 java . lang . object, % 20以% 20 java . 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发布的可能重复的链接。虽然这种做法通常是糟糕设计的标志,所以如果你可以把它去掉,我会的。

根据另一个答案中的建议通过反射设置字段可以工作。

但是,如果您经常做这种事情,我建议使用PowerMock(与Mockito结合使用)或JMockIt来实现这一点。两者都允许模拟构造函数、静态函数、final字段……简而言之,什么都可以。对于遗留代码非常有用。

然而,当你在编写新代码时,你的类依赖于另一个你想用这种方式隔离的类,你应该考虑改变设计,使其他对象被传递给你的类,而不是被它实例化。搜索"Dependency injection",你会发现很多…

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

protected newAnotherClass() { return new AnotherClass(); }
这样,我就可以从单元测试中重写这个方法。它很脏,但是很快:-)

这是一个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...
    }};
}

相关内容

  • 没有找到相关文章

最新更新