无法在静态方法 Powermock 中模拟函数
Unable to Mock functions inside static method Powermock
我正在使用 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。现在感觉有点像新的。如果代码中有任何错误,请纠正我。
您需要更改 PrepareForTest
注释
至 @PrepareForTest({Abc.class})
.
来自 PowerMockito docu
:
This annotation tells PowerMock to prepare certain classes for testing. Classes needed to be defined using this annotation are typically those that needs to be byte-code manipulated
在这种情况下,指的是创建 ServerSocket
的新实例的 class。
ServerSocket
本身是一个 non-final
public
class 不需要 PowerMockito
的特殊处理(相反 Mockito
可以自己处理这个 class)。
您还可以更改测试以执行以下操作:
@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
class 更改为一个对象。
@InjectMocks
对我来说失败了,因为没有默认构造函数
(实际上我在尝试执行您的代码时在控制台中收到一条错误消息)
此外,您在测试中创建了一个新的 ABC 实例,这将覆盖注释所做的事情。此外,由于 server
是在 init
调用期间创建的,因此无需为其注入模拟。
powermockito 2.0.2
实际上取决于 junit 4.12
,所以我不确定降级到旧版本可能会有什么影响。
Socket mockClient
似乎与您发布的代码有些无关,因此我将其从答案中的示例中删除,但是当您使用 client
(我假设是你的 Socket
) 在你的代码中,你可能还需要为此做一些模拟,并相应地为方法提供模拟。
我正在使用 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。现在感觉有点像新的。如果代码中有任何错误,请纠正我。
您需要更改 PrepareForTest
注释
至 @PrepareForTest({Abc.class})
.
来自 PowerMockito docu
:
This annotation tells PowerMock to prepare certain classes for testing. Classes needed to be defined using this annotation are typically those that needs to be byte-code manipulated
在这种情况下,指的是创建 ServerSocket
的新实例的 class。
ServerSocket
本身是一个 non-final
public
class 不需要 PowerMockito
的特殊处理(相反 Mockito
可以自己处理这个 class)。
您还可以更改测试以执行以下操作:
@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
class 更改为一个对象。
@InjectMocks
对我来说失败了,因为没有默认构造函数
(实际上我在尝试执行您的代码时在控制台中收到一条错误消息)此外,您在测试中创建了一个新的 ABC 实例,这将覆盖注释所做的事情。此外,由于
server
是在init
调用期间创建的,因此无需为其注入模拟。powermockito 2.0.2
实际上取决于junit 4.12
,所以我不确定降级到旧版本可能会有什么影响。Socket mockClient
似乎与您发布的代码有些无关,因此我将其从答案中的示例中删除,但是当您使用client
(我假设是你的Socket
) 在你的代码中,你可能还需要为此做一些模拟,并相应地为方法提供模拟。