mockito模拟带参数的构造函数

我有一个类如下:

public class A { public A(String test) { bla bla bla } public String check() { bla bla bla } } 

构造函数A(String test)check()中的逻辑是我试图模拟的东西。 我想要任何电话,如: new A($$$any string$$$).check()返回一个虚拟的string“testing”。

我试过了:

  A a = mock(A.class); when(a.check()).thenReturn("test"); String test = a.check(); // to this point, everything works. test shows as "tests" whenNew(A.class).withArguments(Matchers.anyString()).thenReturn(rk); // also tried: //whenNew(A.class).withParameterTypes(String.class).withArguments(Matchers.anyString()).thenReturn(rk); new A("random string").check(); // this doesn't work 

但它似乎并没有工作。 new A($$$any string$$$).check()仍然通过构造函数逻辑,而不是获取A的模拟对象。

您发布的代码适用于最新版本的Mockito和Powermockito。 也许你没有准备好A? 尝试这个:

A.java

 public class A { private final String test; public A(String test) { this.test = test; } public String check() { return "checked " + this.test; } } 

MockA.java

 import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest(A.class) public class MockA { @Test public void test_not_mocked() throws Throwable { assertThat(new A("random string").check(), equalTo("checked random string")); } @Test public void test_mocked() throws Throwable { A a = mock(A.class); when(a.check()).thenReturn("test"); PowerMockito.whenNew(A.class).withArguments(Mockito.anyString()).thenReturn(a); assertThat(new A("random string").check(), equalTo("test")); } } 

这两个testing都应该通过mockito 1.9.0,powermockito 1.4.12和junit 4.8.2

据我所知,你不能用mockito模拟构造函数,只能使用方法。 但根据Mockito的谷歌代码页上的wiki,有一种方法可以通过在类中创build一个返回该类的新实例的方法来模拟构造函数的行为。 那么你可以嘲笑这种方法。 以下是直接来自Mockito wiki的摘录 :

模式1 – 使用单线方法创build对象

要使用模式1(testing一个名为MyClass的类),可以replace类似的调用

  Foo foo = new Foo( a, b, c ); 

  Foo foo = makeFoo( a, b, c ); 

并写一个单行的方法

  Foo makeFoo( A a, B b, C c ) { return new Foo( a, b, c ); } 

在方法中不包含任何逻辑是很重要的。 只是创build对象的一行。 原因是这个方法本身不会被unit testing。

当你来testing这个类的时候,你testing的这个对象实际上是一个Mockito间谍,这个方法被覆盖,返回一个模拟。 因此,你正在testing的不是这个类本身,而是它的一个非常微小的修改版本。

你的testing类可能包含类似的成员

  @Mock private Foo mockFoo; private MyClass toTest = spy(new MyClass()); 

最后,在你的testing方法中,你可以用类似的方法来模拟makeFoo的调用

  doReturn( mockFoo ) .when( toTest ) .makeFoo( any( A.class ), any( B.class ), any( C.class )); 

如果要检查传递给构造函数的参数,可以使用比任何()更具体的匹配器。

如果你只是想返回你的class级的嘲弄的对象,我认为这应该为你工作。 无论如何,你可以在这里阅读更多关于模仿对象创build的知识:

http://code.google.com/p/mockito/wiki/MockingObjectCreation

没有使用Powermock ….看到下面的例子基于本Glasser答案,因为它花了我一些时间来弄清楚..hope节省了一些时间…

原始类:

 public class AClazz { public void updateObject(CClazz cClazzObj) { log.debug("Bundler set."); cClazzObj.setBundler(new BClazz(cClazzObj, 10)); } } 

修改后的类:

 @Slf4j public class AClazz { public void updateObject(CClazz cClazzObj) { log.debug("Bundler set."); cClazzObj.setBundler(getBObject(cClazzObj, 10)); } protected BClazz getBObject(CClazz cClazzObj, int i) { return new BClazz(cClazzObj, 10); } } 

testing类

 public class AClazzTest { @InjectMocks @Spy private AClazz aClazzObj; @Mock private CClazz cClazzObj; @Mock private BClazz bClassObj; @Before public void setUp() throws Exception { Mockito.doReturn(bClassObj) .when(aClazzObj) .getBObject(Mockito.eq(cClazzObj), Mockito.anyInt()); } @Test public void testConfigStrategy() { aClazzObj.updateObject(cClazzObj); Mockito.verify(cClazzObj, Mockito.times(1)).setBundler(bClassObj); } } 

Mockito有限制testing最终的,静态的和私有的方法。

有了jMockittesting库,你可以做很less的事情,非常简单和直接,如下所示:

一个java.io.File类的模拟构造函数:

 new MockUp<File>(){ @Mock public void $init(String pathname){ System.out.println(pathname); // or do whatever you want } }; 
  • 公共构造函数名称应该用$ initreplace
  • 抛出的参数和exception保持不变
  • 返回types应该被定义为void

模拟一个静态方法:

  • 从方法模拟签名中移除静态
  • 否则方法签名保持不变