无法在静态方法Powermock中模拟功能

时间:2019-08-27 11:17:01

标签: junit mockito junit4 powermockito

我正在使用junit和mockito为以下代码编写单元测试

 public class Abc implements Runnable
    {
        private static ServerSocket server;  
        private static int port;      
        public Abc(int cPort)
        {
            port = cPort;
        }

        public void run()
        {
            init();
        }

        public static void init()
        {
            try {
                server = new ServerSocket(port);
                ...something...
                client.close();
                } 
            }
            catch(IOException e)
            {   
                System.out.println("Exception inside init()...");
                e.printStackTrace();
            }
        }
    };

我编写的单元测试

@RunWith(PowerMockRunner.class)
@PrepareForTest({ServerSocket.class})
public class abcTest {

    @Mock (name = "server") //same name as private var.
    ServerSocket mockServer;        
    @InjectMocks
    Abc abc;

    @Test
    public void testInit() throws Exception {
        int port = 1880;
        Socket mockClient = Mockito.mock(Socket.class);  
        PowerMockito.whenNew(ServerSocket.class).
                withArguments(anyInt()).thenReturn(mockServer);         
        abc = new Abc(port);
        Abc.init();         
        PowerMockito.verifyNew(ServerSocket.class).withArguments(port);
    }
};

但是调用总是转到原始函数定义。我正在将junit 4.11与mockito 2.28.2和powermockito 2.0.2一起使用。我使用Java很久了。现在感觉就像是新的一样。如果代码中有任何错误,也请纠正我。

1 个答案:

答案 0 :(得分:1)

您将需要更改PrepareForTest批注 到@PrepareForTest({Abc.class})

从PowerMockito docu

  

此注释告诉PowerMock准备某些类进行测试。需要使用此注释定义的类通常是那些需要字节码操作的类

在这种情况下,它引用创建ServerSocket的新实例的类。
ServerSocket本身是一个non-final public类,不需要PowerMockito的特殊处理(相反,Mockito可以自己处理此类)。


您还可以更改测试以执行以下操作:

@Test
public void testInit() throws Exception {
    int port = 1880;

    ServerSocket mockServer = Mockito.mock(ServerSocket.class);

    PowerMockito.whenNew(ServerSocket.class)
                .withArguments(Mockito.anyInt()).thenReturn(mockServer);

    Abc.port = port;
    Abc.init();     

    PowerMockito.verifyNew(ServerSocket.class).withArguments(port);
}

  • (第一点与测试是否成功无关)
    我不知道为什么将对象和静态方法的行为混合在一起,但是我认为您应该对此进行更改。

    在测试中,不必创建ABC对象,只需设置静态对象即可。端口变量直接。
    或者,将整个ABC类更改为一个对象。

  • @InjectMocks对我来说失败了,因为没有默认的构造函数
    (实际上,在尝试执行您的代码时,控制台中出现错误消息)

  • 此外,您将在测试中创建一个新的ABC实例,该实例将覆盖注释所完成的工作。同样,由于在server调用期间创建了init,因此无需为其注入模拟。

  • powermockito 2.0.2实际上取决于junit 4.12,所以我不确定降级到较旧版本会产生什么影响。

  • Socket mockClient似乎与您发布的代码无关,因此我从答案中的示例中删除了它,但是当您使用client时(我假设您的{{1 }})在您的代码中,您可能还需要对此进行一些模拟,并相应地向该方法提供模拟。