【问题标题】:how to mock with mockito如何用 mockito 模拟
【发布时间】:2016-07-15 16:52:42
【问题描述】:

我的 MainActivity (Android) 中有一个方法,我想模​​拟 A 实例:

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

所以我创建了一种工厂类

public class SomeFactory(){

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

上面的方法变成了

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

我试过了

@Mock
    SomeFactory someFactory;

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

        mainActivity.some_method(someFactory);
...
    }

但我收到此错误消息

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

【问题讨论】:

    标签: java android unit-testing mocking


    【解决方案1】:

    你不是在嘲笑你的工厂。还有,错误的方法调用。

    改为这样做。

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

    更新

    您的代码已更改,因此为了完整起见,您的测试应该是这样的。在上面更新的代码中,你用一个真实的对象覆盖了你的mock。假设您的对象设置正确。注意提供返回对象的不同语法。我认为这更具可读性。

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

    最佳实践

    • 命名方法和变量时,使用驼峰命名法。所以main_activity 变成了MainActivitysome_method 变成了SomeMethod

    【讨论】:

    • 非常感谢您的回复。事实上,我输入thenReturn(null) 只是为了简单,但我需要thenReturn(new A) 之类的东西。所以,当我这样做时,我遇到了一个问题,因为在创建对象A a 之后,有一个方法调用a.method_call(),但随后我得到了java.lang.NullPointerException: Attempt to invoke virtual method "some.package.method_call" on a null object reference。你知道如何解决这个问题吗?
    • 那么在你的A类中有对method_call的调用吗?我也需要查看该代码。
    • 抱歉,我在编辑帖子时遇到了问题。现在是正确的
    • 感谢您的回复:现在我收到此消息Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference at com.google.dexmaker.mockito.DexmakerMockMaker.getInvocationHandlerAdapter
    • 我在这篇文章中找到了解决我的问题https://stackoverflow.com/questions/30590470/npe-when-calling-mockitoannotations-initmocks-in-androidtestcase 的方法。但是,我得到了NullPointerException: Attempt to invoke virtual method 'my.package.A my.factory.populateWithParameter(Parameter )' on a null object reference
    【解决方案2】:

    您需要一种方法来覆盖测试中的 A 实例。通常这是使用注入框架完成的。对于一个简单的情况,您可以将被测字段设为protected(假设测试类与被测类在同一个包中)。

    您看到的错误来自与“真实”对象的交互,就好像它是一个模拟对象一样。

    在这种情况下SomeFactory 是一个真实的对象,所以它不可能是when()ed

    【讨论】:

      【解决方案3】:

      从@DiscoS2的回应来看,这个声明确实有问题

      MockitoAnnotations.initMocks(this);
      

      您应该改用SomeFactory someFactory = mock(SomeFactory.class),然后按照@DiscoS2 的更新响应

      【讨论】:

        猜你喜欢
        • 2018-10-08
        • 2019-08-22
        • 1970-01-01
        • 1970-01-01
        • 2016-05-08
        • 2012-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多