使用Mockito的Java Mock最终void方法

时间:2018-09-20 05:55:49

标签: java unit-testing mockito

在了解如何对以下内容进行单元测试时,我需要一些帮助。我有下面的类结构。我必须遵循结构,因为这是根据我们产品的框架,所以我不能偏离它。

package com.rohan.base

import javax.inject.Inject;

public abstract class ServiceBase {

    @Inject
    protected CommandExecutorBase commandExecutor;

    public final void execute() {
        commandExecutor.execute(this);
    }   
}

--------------------------------------------------------

package com.rohan.services

public class MyService extends ServiceBase {
    public void someMethod() {} 
}

--------------------------------------------------------

package com.rohan.delegates

import javax.inject.Inject;
import com.rohan.services.MyService

public class MyDelegate {

    @Inject
    MyService myService;

    public void callService() {
        myService.execute();
    }   
}

我正在尝试使用TDD方法进行编码,并且我想确保委托类中的callService方法在Service类上调用execute方法。

我尝试了以下方法,但是它给我execute方法中的Null Pointer异常(因为commandExecutor对象为null)。 有人可以告诉我我该怎么做吗? 我不允许使用PowerMockito。

import org.junit.Test;
import org.mockito.Mockito;

public class MyDelegateUnitTests {

    @Test
    public void validateServiceExecuteIsCalled() {
        MyDelegate delegate = new MyDelegate();
        MyService serviceObject = Mockito.mock(MyService.class);
        delegate.myService = serviceObject;
        Mockito.doAnswer((i) -> {
            System.out.println("I am here");
            return null;
        }).when(serviceObject).execute();
        Mockito.verify(serviceObject, Mockito.times(1)).execute();
    }   
}

我无法模拟commandExecutor对象,因为该对象不可访问(与我的Delegate类不同的程序包)。 我还代替Mockito.doAnswer(),尝试了Mockito.doNothing().when(serviceObject).execute();
但是我也有同样的例外。当我尝试在when方法中定义模拟时,有人可以建议我,为什么它继续尝试并执行真实方法? 谢谢!

更新 我修改了测试类,并添加了文件夹/文件嘲笑扩展名(由@jokster在下面的答案中建议)。但是,我最终遇到以下异常。我正在使用Mockito 2。

我的测试班:

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;

public class MyDelegateUnitTests {

    MyDelegate delegate;
    MyService serviceObject;

    @Before
    public void setUpMocks() {
        delegate = new MyDelegate();
        serviceObject = Mockito.mock(MyService.class);
        Mockito.doNothing().when(serviceObject).execute();
        delegate.myService = serviceObject;     
    }

    @Test
    public void validateSettersAreCalled() {
        delegate.callService();
        Mockito.verify(serviceObject, Mockito.times(1)).execute();
    }
}

我得到以下异常:

java.lang.ExceptionInInitializerError: null
        at org.mockito.internal.configuration.plugins.Plugins.getStackTraceCleanerProvider(Plugins.java:17)
        at org.mockito.internal.exceptions.stacktrace.StackTraceFilter.<clinit>(StackTraceFilter.java:21)
        at org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter.<init>(ConditionalStackTraceFilter.java:17)
        at org.mockito.exceptions.base.MockitoException.filterStackTrace(MockitoException.java:41)
        at org.mockito.exceptions.base.MockitoException.<init>(MockitoException.java:30)
        at org.mockito.exceptions.misusing.MockitoConfigurationException.<init>(MockitoConfigurationException.java:18)
        at org.mockito.internal.configuration.plugins.PluginLoader.loadImpl(PluginLoader.java:66)
        at org.mockito.internal.configuration.plugins.PluginLoader.loadPlugin(PluginLoader.java:24)
        at org.mockito.internal.configuration.plugins.PluginRegistry.<init>(PluginRegistry.java:12)
        at org.mockito.internal.configuration.plugins.Plugins.<clinit>(Plugins.java:11)
        at org.mockito.internal.util.MockUtil.<clinit>(MockUtil.java:24)
        at org.mockito.internal.MockitoCore.<init>(MockitoCore.java:44)
        at org.mockito.Mockito.<clinit>(Mockito.java:975)
        at com.rohan.delegates.MyDelegateUnitTests.setUpMocks(MyDelegateUnitTests.java:16)

2 个答案:

答案 0 :(得分:0)

根据本文档https://www.baeldung.com/mockito-final,您必须激活模拟最终方法:只需创建文件src/test/resources/mockito-extensions/mock-marker-inline

然后,最终方法应该与其他方法一样工作。

答案 1 :(得分:0)

作为单元测试的一部分,我认为不需要定义myService.execute方法的行为。定义行为是不必要的

 Mockito.doAnswer((i) -> {
        System.out.println("I am here");
        return null;
    }).when(serviceObject).execute();

您可以删除上面的代码。

足以验证execute方法被调用了正确的次数。为了回答您的问题,一个建议是与基于构造函数的注入有关。基本上为MyDelegate创建一个构造函数并注入Myservice。在测试中,请执行以下操作:

MyService serviceObject = Mockito.mock(MyService.class);      
MyDelegate delegate = new MyDelegate(serviceObject);

如果您不希望在委托类中使用基于构造函数的注入,则其他选择是在测试中使用@InjectMocks@Inject