如何在不初始化类的情况下模拟内部成员

时间:2016-01-02 12:04:28

标签: java unit-testing testing mocking mockito

我想为下面的类编写单元测试:

public class Target() {

    private final Member member = new Member();

    public Target() {
    } 

}

我想使用模拟的Member实例初始化此Target类,因为在测试期间实例化Member是不可行的。这可能适用于任何框架吗?

编辑:

我不想模拟Target类。我打算在初始化时模拟Member类。

Object method() {
    member.differentMethod();
    //Logic which I want to test
}

请建议如何模拟对Member类方法的调用。

3 个答案:

答案 0 :(得分:2)

您可以constructor mocking使用Powermock

@RunWith(PowerMockRunner.class)
@PrepareForTest(Target.class)
public class Test {
    @Test
    public void doSomething() throws Exception {
        Member mockMember = mock(Member.class);
        PowerMockito.whenNew(Member.class).thenReturn(mockMember);
        Target thisTargetWillHaveYourMockAsField = new Target();
        //Your test code
    }
}

答案 1 :(得分:2)

为了建立Prim的答案(upvoted),给自己两个构造函数。

public class Target() {

  private final Member member;

  public Target() {
    this.member = new Member();
  }

  /** Testing constructor. Package-private visibility for tests in the same package. */
  Target(Member member) {
    this.member = member;
  }    
}

通过提供多个构造函数,您可以确保生产中的消费者根本不需要更改。这也是"测试代码污染生产的一个独特案例":您的一个用例(特别是测试)需要一个自定义的Member实现,并且您提供了最大的封装访问权限来替换该成员为spec' ed。

另请参阅: How to use Mockito when we cannot pass a mock object to an instance of a class

答案 2 :(得分:1)

您应该将Target类的成员使用实例传递给Target类的构造函数。

通过这样做,您可以在生产环境中使用您的Member类的实现,并在测试环境中使用另一个实现(可能为空)。

最佳和最佳解决方案是使用依赖性反转/注入原则