我正在使用 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);
}
};
但是调用始终转到原始函数定义。我正在使用带有 mockito 2.28.2 和 powermockito 2.0.2 的 junit 4.11。很长一段时间后,我正在使用java。现在它感觉有点新。如果代码中有任何错误,请纠正我。
您需要更改PrepareForTest
注释 到@PrepareForTest({Abc.class})
.
来自PowerMockitodocu
:
此注释告诉 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
(我假设这是您的Socket
(时,您可能也需要为此做一些模拟,并相应地为该方法提供模拟。