简体   繁体   English

如何用模拟嘲笑

[英]how to mock with mockito

I have a method in my MainActivity (Android) and I want to mock the A instance : 我的MainActivity (Android)中有一个方法,我想模​​拟A实例:

public void some_method() {
    A a = new A(); 
    ....   
}

so I created a kind of factory class as such 所以我创建了这样的工厂类

public class SomeFactory(){

 // some constructor
public A populateWithParameter(Parameter parameter){
 return new A(parameter)
} 
}

and the method above turns into 上面的方法变成

public void some_method(SomeFactory someFactory) {
        A a = someFactory.populateWithParameter(parameter); 
        a.method_call()        
        ....   
    }

I tried this 我试过了

@Mock
    SomeFactory someFactory;

public void testSomeMethod() throws Exception {
        SomeFactory someFactory = new SomeFactory();
        when(someFactory.populateWithParameter(
                some_parameter)).thenReturn(null);

        mainActivity.some_method(someFactory);
...
    }

but I get this error message 但我收到此错误消息

    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);

You are not mocking your factory. 您不是在嘲笑您的工厂。 Also, wrong method call. 另外,错误的方法调用。

Do this instead. 改为这样做。

    SomeFactory someFactory = mock(SomeFactory.class)
    when(someFactory.populateWithParameter(
            some_parameter)).thenReturn(null);

    mainActivity.some_method(someFactory);

UPDATE 更新

Your code has changed so for completeness this is what your test should look like. 您的代码已更改,因此为了完整起见,这就是您的测试的外观。 In the updated code above, you were overwriting your mock with a real object. 在上面的更新代码中,您正在用真实对象覆盖mock Assuming your objects are correctly set up. 假设您的对象设置正确。 Notice the different syntax for providing a return object. 注意提供返回对象的不同语法。 I think this is more readable. 我认为这更具可读性。

@Mock SomeFactory mockFactory;

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this); // set up annotated mocks
}

@Test
public void testSomeMethod() {
    A subject = new A();
    doReturn(subject).when(mockFactory)
                        .populateWithParameter(any(Parameter.class));
    main_activity.some_method(mockFactory);
    verify(mockFactory,times(1)).populateWithParameter(any(Parameter.class));
}

Best Practices 最佳实践

  • When naming methods and variables, use camelCase. 在命名方法和变量时,请使用camelCase。 So main_activity becomes MainActivity , some_method becomes SomeMethod . 所以main_activity变成MainActivitysome_method变成SomeMethod

You need a way to overwrite the instance of A from your test. 您需要一种方法来覆盖测试中的A实例。 Typically this is done using an injection framework. 通常,这是使用注入框架完成的。 For a simple case, you can make the field under test protected (assuming the test class is in the same package as the class under test). 对于一个简单的例子,您可以将被测字段设置为protected (假设测试类与被测类位于同一包中)。

The error you are seeing comes interacting with a "real" object as if it was a mock. 您看到的错误是与“真实”对象进行交互,就好像它是模拟对象一样。

In this case SomeFactory is a real object so it cannot be when()ed 在这种情况下, SomeFactory是一个真实的对象,因此它不可能是when()ed

From the point of view of response of @DiscoS2, there is indeed an issue with this declaration 从@ DiscoS2的响应角度来看,此声明确实存在问题

MockitoAnnotations.initMocks(this);

You should use instead SomeFactory someFactory = mock(SomeFactory.class) and then follow the updated response of @DiscoS2 您应该改用SomeFactory someFactory = mock(SomeFactory.class) ,然后遵循@ DiscoS2的更新响应

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

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