嘲笑Java接口中的方法时与Mockito的问题

发布于 2025-01-30 14:58:06 字数 3023 浏览 5 评论 0原文

使用Junit5和Mockito 3.8嘲笑Java接口中的方法时,我有问题。该测试失败了:

Wanted but not invoked:
remoteCommands.getServiceStatus("ABC");
-> at com.acme.CommandHandlerTest.testServiceName(CommandHandlerTest.java:40)
Actually, there were zero interactions with this mock.

它在CommandHandlertest.java的40行失败,但是

verify(remoteCommands).getServiceStatus(serviceName);

,当我调试代码时,我可以看到正在执行的方法,因此我知道与此方法有1个相互作用,但Mockito无法识别它。

请建议我是否缺少什么?我的代码文件如下,

commandhandlertest.java

package com.acme;

import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.rmi.RemoteException;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class  CommandHandlerTest {

    private CommandHandler commandHandler;
    
    @Mock
    IRemoteCommandsImpl remoteCommands;
    
    @BeforeEach
    void setup() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    void testDoCommand_serviceName() throws RemoteException {
        commandHandler = new CommandHandler();
        
        String serviceName = "ABC";
        int mockValue = 4000;

        when(remoteCommands.getServiceStatus(eq(serviceName))).thenReturn(mockValue);
        
        commandHandler.printServiceStatus(serviceName);
        
        verify(remoteCommands).getServiceStatus(serviceName);
        
    }
}

commandhandler.java

package com.acme;

public class CommandHandler {

    private IRemoteCommands remoteCommands;
    
    public CommandHandler(){

    }

    public void printServiceStatus(String service) {

        remoteCommands = new IRemoteCommandsImpl();
        int serviceStatus = 0;

        try {
            serviceStatus = remoteCommands.getServiceStatus(service);
            System.out.println("CommandHandler->serviceStatus: "+serviceStatus);
        } catch (Exception e) {
            e.getMessage();
        }
    }
}

iremotecommands.java

package com.acme;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface IRemoteCommands extends Remote
{

    public int getServiceStatus(String serviceName) throws RemoteException;

}

iremotecommandsimpl.java

package com.acme;
import java.rmi.RemoteException;

public class IRemoteCommandsImpl implements IRemoteCommands{

    @Override
    public int getServiceStatus(String serviceName) throws RemoteException {
        return 1000;
    }
}

I'm having issues when mocking a method in Java interface using Junit5 and Mockito 3.8. The test is failing with the reason:

Wanted but not invoked:
remoteCommands.getServiceStatus("ABC");
-> at com.acme.CommandHandlerTest.testServiceName(CommandHandlerTest.java:40)
Actually, there were zero interactions with this mock.

its failing at line 40 of CommandHandlerTest.java which is

verify(remoteCommands).getServiceStatus(serviceName);

However, when I debug the code, I can see the method being executed so I know there is 1 interaction with this method but Mockito can't recognise it.

Please can you advise if I am missing something? My code files are as below,

CommandHandlerTest.java

package com.acme;

import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.rmi.RemoteException;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class  CommandHandlerTest {

    private CommandHandler commandHandler;
    
    @Mock
    IRemoteCommandsImpl remoteCommands;
    
    @BeforeEach
    void setup() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    void testDoCommand_serviceName() throws RemoteException {
        commandHandler = new CommandHandler();
        
        String serviceName = "ABC";
        int mockValue = 4000;

        when(remoteCommands.getServiceStatus(eq(serviceName))).thenReturn(mockValue);
        
        commandHandler.printServiceStatus(serviceName);
        
        verify(remoteCommands).getServiceStatus(serviceName);
        
    }
}

CommandHandler.java

package com.acme;

public class CommandHandler {

    private IRemoteCommands remoteCommands;
    
    public CommandHandler(){

    }

    public void printServiceStatus(String service) {

        remoteCommands = new IRemoteCommandsImpl();
        int serviceStatus = 0;

        try {
            serviceStatus = remoteCommands.getServiceStatus(service);
            System.out.println("CommandHandler->serviceStatus: "+serviceStatus);
        } catch (Exception e) {
            e.getMessage();
        }
    }
}

IRemoteCommands.java

package com.acme;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface IRemoteCommands extends Remote
{

    public int getServiceStatus(String serviceName) throws RemoteException;

}

IRemoteCommandsImpl.java

package com.acme;
import java.rmi.RemoteException;

public class IRemoteCommandsImpl implements IRemoteCommands{

    @Override
    public int getServiceStatus(String serviceName) throws RemoteException {
        return 1000;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

白色秋天 2025-02-06 14:58:06

在您的CommandHandler中,您创建了一个新实例iRemoteCommandSimpl,然后将其分配给private remotecommands字段。

这意味着您模拟的remoteCommands未经测试的对象未使用。

您需要重组代码,并提供remoteCommands commandhandler ,最好是通过构造函数:

public class CommandHandler {

    private final IRemoteCommands remoteCommands;
    
    public CommandHandler(IRemoteCommands remoteCommands) {
        this.remoteCommands = remoteCommands;
    }
    // ...
}

最重要的是:

  • 您不需要opoceToantoAnnotations.openmocks(this); 如果您使用MockItoextension

In your CommandHandler, you create a new instance of IRemoteCommandsImpl and assign it to private remoteCommands field.

This means that your mocked remoteCommands is not used by object under test.

You need to restructure your code and provide remoteCommands to CommandHandler, preferably by constructor:

public class CommandHandler {

    private final IRemoteCommands remoteCommands;
    
    public CommandHandler(IRemoteCommands remoteCommands) {
        this.remoteCommands = remoteCommands;
    }
    // ...
}

On top of that:

  • you dont need MockitoAnnotations.openMocks(this); if you use MockitoExtension
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文