简体   繁体   English

Mock 不适用于新对象创建

[英]Mock is not applied on new object creation

I was trying to mock a new object creation我试图模拟一个新的对象创建

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

Error:错误:

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.此外,出现此错误的原因可能是: 1. 您存根了以下任一方法: final/private/equals()/hashCode() 方法。 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. 2. 在 when() 中,您不会在模拟上调用方法,而是在其他对象上调用方法。

I did mock the myClass object, but it is getting assigned to a new object on method call:我确实模拟了 myClass 对象,但它在方法调用时被分配给一个新对象:

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

First: I recommend to not use PowerMock.第一:我建议不要使用 PowerMock。 As using this framework often results in bizarre errors, and: you have to understand that you are not facing a "deficiency" of Mockito ... but a deficiency in your design.因为使用这个框架经常会导致奇怪的错误,并且:你必须明白你面临的不是 Mockito 的“缺陷”......而是你的设计缺陷。

Basically, you want to learn about using dependency injection .基本上,您想了解使用依赖注入 The whole idea is: you do not call new within your production code.整个想法是:您不要在生产代码中调用new Because, you can't mock calling "new".因为,你不能模拟调用“new”。 Instead, you push the objects that your production code needs ... into your classes.相反,您将生产代码需要的对象推送到您的类中。

For normal (production) work, you push normal objects;对于正常(生产)工作,您推送正常对象; and for unit testing, you push in mocked objects.对于单元测试,你推入模拟对象。

In other words: if you figure that your design would require PowerMock to be tested;换句话说:如果您认为您的设计需要对 PowerMock 进行测试; then that tells you that your design needs to be reworked.那么这告诉你你的设计需要重新设计。

This is correct behavior;这是正确的行为; Mockito doesn't support mocking new object creation. Mockito 不支持模拟新对象的创建。 You'll need another library like PowerMock for that, or you'll need to refactor your test.为此,您将需要另一个类似PowerMock 的库,或者您需要重构您的测试。

To learn a little more about each part of a Mockito-based test:要了解有关基于 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 creates a mock object. mock创建一个模拟对象。 Note that you're not setting expectations on all instances of MyObject;请注意,您并未对 MyObject 的所有实例设置期望值; instead, you're creating a single instance to control.相反,您正在创建一个要控制的实例。 Internally, this is actually a one-off subclass of MyObject with all its methods overridden, so Mockito is only really good for visible non-final instance methods (that you could override yourself).在内部,这实际上是 MyObject 的一次性子类,其所有方法都被覆盖,因此 Mockito 仅适用于可见的非最终实例方法(您可以自己覆盖)。

  2. You can use the when call to stub behavior.您可以使用when调用存根行为。 The only thing that can go inside when is a single call to a method on a Mockito-created mock , so your new keyword won't work here.唯一可以进入的when对 Mockito 创建的 mock 上的方法单次调用,因此您的new关键字在这里不起作用。

  3. Again, because you can't use new , you'll generally need to insert your mock into your system under test.同样,因为您不能使用new ,您通常需要将您的模拟插入到您的被测系统中。 You (almost) never mock the system under test;你(几乎)从不嘲笑被测系统; you're mocking the collaborator instead, and since you can't use new you generally have to pass it in. This is part of why Mockito works so well with dependency injection systems .你是在嘲笑合作者,因为你不能使用new你通常必须将它传递进来。这就是为什么 Mockito 与依赖注入系统一起工作如此出色的部分原因

  4. Then you call your method-under-test...然后你调用你的被测方法......

  5. ...and check that the final state is what you want it to be. ...并检查最终状态是否是您想要的状态。 This can be assertions like assertEquals from a test framework, calls to verify using Mockito-created mocks, or some combination of the two.这可以是来自测试框架的assertEquals之类的断言,使用 Mockito 创建的模拟调用verify ,或两者的某种组合。

Remember, with just Mockito, you will not be able to have Java return a mock when calling new , so you'll need a step like step 3 above.请记住,仅使用 Mockito,您将无法在调用new时让 Java 返回模拟,因此您需要执行类似于上面第 3 步的步骤。 Alternatively, PowerMock is an extension library on top of EasyMock or Mockito, which has static methods like whenNew and mockStatic for more advanced mocking.或者, PowerMock是 EasyMock 或 Mockito 之上的扩展库,它具有诸如whenNewmockStatic类的静态方法,用于更高级的mockStatic (A word of caution, though: Because PowerMock uses a special classloader to rewrite your classes, it can be more difficult to set up, and its magic may make your tests harder to reason about. Refactoring may be a better way to keep your tests understandable.) (不过,请注意:因为 PowerMock 使用特殊的类加载器来重写您的类,所以设置起来可能会更加困难,而且它的魔力可能会使您的测试更难推理。重构可能是保持测试的更好方法可以理解。)

You can try powermock.你可以试试powermock。 It worked for me.它对我有用。

import org.powermock.api.mockito.PowerMockito;

MyClass myClassMock = Mockito.spy(new MyClass());
PowerMockito.whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
public class MyServiceTest {    
    MyClass myClass;
    myClass = PowerMockito.mock(MyClass.class);
    PowerMockito.whenNew(MyClass.class).thenReturn(myClass);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM