模拟不适用于新对象创建

时间:2016-05-03 03:53:23

标签: junit mockito

我试图模拟一个新的对象创建

public class MyServiceTest {    
  MyClass myClass;
  myClass = Mockito.mock(MyClass.class);
  Mockito.when(new MyClass()).thenReturn(myClass);
}

错误:

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
   Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.

我确实模拟了myClass对象,但它被分配给方法调用上的新对象:

public class MyService {
  public static String myMethod(){
    MyClass myClass = new MyClass();
    //..........
  } 
}

4 个答案:

答案 0 :(得分:2)

首先:我建议不要使用PowerMock。使用这个框架经常导致奇怪的错误,并且:你必须明白你并没有面对Mockito的“缺陷”......但是你的设计存在缺陷。

基本上,您想了解如何使用dependency injection。整个想法是:您不要在生产代码中调用 new 。因为,你不能模拟调用“新”。相反,您将生产代码所需的对象推送到您的类中。

对于正常(生产)工作,您可以推送普通对象;对于单元测试,您可以推送模拟对象。

换句话说:如果您认为您的设计需要测试PowerMock;然后告诉你你的设计需要重新设计。

答案 1 :(得分:1)

这是正确的行为; Mockito并不支持模拟新对象的创建。你需要另外一个像PowerMock这样的库,或者你需要重构你的测试。

要了解有关基于Mockito的测试的每个部分的更多信息:

/* 1 */  MyObject myObjectMock = Mockito.mock(MyObject.class);
/* 2 */  when(myObjectMock.methodCall()).thenReturn("return value");
/* 3 */  MySystemUnderTest systemUnderTest = new MySystemUnderTest(myObjectMock);
/* 4 */  systemUnderTest.methodToTest();
/* 5 */  verify(myObjectMock).methodCalledByTheSystemUnderTest();
  1. mock创建一个模拟对象。请注意,您并未在MyObject的所有实例上设置期望值;相反,您正在创建一个控件的实例。在内部,这实际上是MyObject的一次性子类,其所有方法都被覆盖,因此Mockito只对可见的非最终实例方法(你可以自己覆盖)非常有用。

  2. 您可以使用when调用存根行为。可以进入when的唯一内容是对Mockito创建的模拟上的方法进行单次调用,因此您的new关键字无法在此处工作。< / p>

  3. 同样,由于您无法使用new,因此您通常需要将模拟插入正在测试的系统中。你(几乎)从不嘲笑被测系统;您反而嘲笑协作者,因为您无法使用new,所以通常必须将其传入。这是why Mockito works so well with dependency injection systems的一部分。

  4. 然后你打电话给你的测试方法......

  5. ...并检查最终状态是否符合您的要求。这可以是来自测试框架的assertEquals等断言,使用Mockito创建的模拟调用verify,或两者的某种组合。

  6. 请记住,只有Mockito,在调用new时,您将无法让Java返回模拟,因此您需要像上面的步骤3那样的步骤。或者,PowerMock是EasyMock或Mockito之上的扩展库,它具有静态方法,如whenNewmockStatic,用于更高级的模拟。 (但请注意:由于PowerMock使用特殊的类加载器来重写类,因此设置起来可能会更加困难,而且它的魔力可能会使您的测试更难以推理。重构可能是保持测试的更好方法可以理解的。)

答案 2 :(得分:0)

你可以尝试使用powermock。它对我有用。

import org.powermock.api.mockito.PowerMockito;

MyClass myClassMock = Mockito.spy(new MyClass());
PowerMockito.whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);

答案 3 :(得分:-1)

somefile.js

import Image from "../assests/img.jpg";

const imgEle=document.createElement("img");
imgEle.src=Image; // gets corrrectly refrenced to md5hash.jpg in the bundle