2 回答

TA贡献1860条经验 获得超9个赞
您可以在类中提供一个函数,该函数读取输入流并模拟它而不是方法:ServerfromClientObjectInputStream.readObject()
public class Server extends Thread {
private Other other;
ObjectInputStream fromClient;
ObjectOutputStream toClient;
public Server(){
this.other = new Other(foo, bar);
}
Object readObject() throws ClassNotFoundException, IOException {
return fromClient.readObject();
}
//...
因此,您的测试将如下所示:
@Test
void run() throws IOException, ClassNotFoundException {
//given
Other other = new Other(foo, bar);
Server server = mock(Server.class);
//when
when(server.readObject()).thenReturn(0x2);
server.start();
//then
verify(server).toClient.writeObject(other.getSomething());
}
同样的事情也可以应用于流。toClient

TA贡献1862条经验 获得超7个赞
问题中的误解
我知道Mockito不能模拟最终类,例如ObjectOutputStream和ObjectInputStream。> 这正是我遇到问题的地方。
到目前为止,我的测试在线NullPointerException失败
when(server.fromClient.readObject()).thenReturn(0x2);.
这是 Mockito 的典型情况,当遇到最终方法时。
您的 NPE 不是由于 Mockitos 无法模拟方法引起的。NPE 的原因是您的成员变量,并且在测试代码尝试访问它们时未初始化。final
fromClient
toClient
但即使如此,它们也会使用真实依赖项的实例进行初始化,而不是使用模拟,因此Mockito无论如何都无法配置它们。
您从根本上误解了 .你永远不会嘲笑你的班级被测试。您始终模拟受测类的依赖项,并将受测代码的实际依赖项替换为此模拟。mocks
在其他文章中有人建议,可以通过实现接口来更改所测试类的签名来规避 -问题,因此无论如何都会模拟它。
final
ObjectInput
不。
您建议针对接口进行编程,而不是针对具体类进行编程,并使用依赖注入/控制反转。
没有人建议你测试的类(这是你的类)应该实现任何接口。Server
违反 OOP 最佳实践
问:“为什么我不将流传递到服务器?
答:因为我在其他任何地方都不需要它们。这真的是最后的努力,如果有必要,我会的,但我宁愿不这样做。
我们做OOP的主要原因之一是我们代码的可重用性。
单元测试是代码最明显的首次重用。在测试代码时遇到困难会发现缺乏可重用性。在这一点上,你的类根本不应该被“重用”并不重要。这是您的通用编码方法,它将使您将来遇到麻烦。Server
您的类存在一些违反 OOP 最佳实践的行为:Server
封装/信息隐藏。
您最有可能将成员变量和包声明为私有,以便能够从我们的测试中访问它们。这在两个方面存在问题:
fromClient
toClient
您的代码永远不应该公开成员变量等实现细节(除了它是DTO/ValueObject)。
切勿为启用测试而显式修改生产代码。
关注点分离
任何类(提供业务逻辑)都应该有一个单一的责任。依赖项的实例化是一个完全不同的责任,这与您的业务逻辑不同。因此,您的类不应负责执行此实例化。
Server
我知道这有点教条,但它会带来更好的可测试性,因此更好的可重用代码。再说一遍:如果你的代码目前根本不打算重用,这并不重要。
结论
恕我直言,您真正的问题是:如何在不适应OOP最佳实践的情况下测试我的代码?
在这种情况下,您应该通过使用PowerMock明确地放弃糟糕的设计。
添加回答
举报