Mockito:模拟一个有多个构造函数的对象?

时间:2017-10-27 00:22:58

标签: java mockito

是否可以模拟一个可能在被测试的类中实例化的对象,该对象不使用依赖注入,并且将根据用于被测试类的c-tor而使用不同的构造函数进行实例化?

2 个答案:

答案 0 :(得分:1)

你的模拟实际上并没有调用构造函数。他们调用一个代理对象,它将解析为该对象类型,但注入了许多运行时实用程序,以便您检查它。

如果您想要来测试构造函数,那么您可能希望在没有模拟的情况下实际实例化它。

答案 1 :(得分:1)

将构造函数调用视为静态调用:如果在代码中调用new Foo(...),Mockito将无法提供替换或模拟Foo(至少在不重写系统的情况下) -under-test,which is what Powermock can do)。无论Foo有多少构造函数,都是如此。

如果你不允许改变被测系统,你就会陷入困境:它不是一个灵活的系统。这不一定是坏事:如果您的系统依赖是轻量级和弹性的,那么您可以确保依赖性经过充分测试,并将其视为您的被测系统的不可更改的实现细节。

如果你想用mock替换你的实例,你可能需要插入一个测试接缝,你可以进入并替换实例,这是一种依赖注入。您可以选择使用工厂,可以将其保存为字段或作为构造函数参数传递:

class YourSystemUnderTest {
  interface FooFactory {
    Foo create(Bar bar);           // one-arg constructor
    Foo create(Bar bar, Baz baz);  // two-arg constructor
  }

  class DefaultFooFactory implements FooFactory {
    @Override public Foo create(Bar bar) { return new Foo(bar); }
    @Override public Foo create(Bar bar, Baz baz) { return new Foo(bar, baz); }
  }

  /** Visible and non-final for testing. */
  FooFactory fooFactory = new DefaultFooFactory();  // replace this in tests

  // ...
}

或者,作为一种稍微苛刻的方法,在您的测试系统中委托一个可覆盖的方法调用,并在测试中覆盖它。

class YourSystemUnderTest {
  /** Visible and non-final for overriding. */
  Foo createFoo(Bar bar) { return new Foo(bar); }
  /** Visible and non-final for overriding. */
  Foo createFoo(Bar bar, Baz baz) { return new Foo(bar, baz); }
}

class YourSystemUnderTest_Test {
  @Mock Foo mockFoo;

  @Before void createSystemUnderTest() {
    yourSystemUnderTest = new YourSystemUnderTest() {
      @Override Foo createFoo(Bar bar) { return mockFoo; }
      @Override Foo createFoo(Bar bar, Baz baz) { return mockFoo; }
    };
  }

  // ...
}

请注意,在这两种情况下,您都准确地表示YourSystemUnderTest不再仅使用真正的Foo实例锁定,而是允许使用其他Foo实现(包括测试双实现)。在测试之外,如果您升级或更改被测系统的依赖项,这可能会派上用场。