Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何执行复杂对象的单元测试?_Java_Unit Testing_Junit - Fatal编程技术网

Java 如何执行复杂对象的单元测试?

Java 如何执行复杂对象的单元测试?,java,unit-testing,junit,Java,Unit Testing,Junit,假设您想为游戏创建单元测试 您有Player类,它有一个World类的局部变量(由构造函数实例化),并且World对象与数据库有一个打开的连接 因此player.breakBlock()方法将调用world.breakBlockAt(x,y,z)和world.breakBlockAt(int x,int y,int z)方法将对数据库执行更改并返回结果 在这种情况下,如果您有复杂的“对象依赖关系”,那么执行测试的最佳方法是什么 目前,我基本上正在启动整个游戏环境,使用一个测试数据库,生成一个假玩

假设您想为游戏创建单元测试

您有
Player
类,它有一个
World
类的局部变量(由构造函数实例化),并且
World
对象与数据库有一个打开的连接

因此
player.breakBlock()
方法将调用
world.breakBlockAt(x,y,z)
world.breakBlockAt(int x,int y,int z)
方法将对数据库执行更改并返回结果

在这种情况下,如果您有复杂的“对象依赖关系”,那么执行测试的最佳方法是什么


目前,我基本上正在启动整个游戏环境,使用一个测试数据库,生成一个假玩家并使用它进行测试。

您可以模拟
玩家中的
世界
对象(使用类似的框架)
,用存根替换
breakBlockAt
,然后验证
breakBlockAt
是否已调用


当然,这需要您能够将这样一个伪造的
世界
注入
玩家
类。

要在没有数据库的情况下测试
玩家
类,您可以使用类似或创建
世界
对象的模拟框架,预先记录希望您的
Player
类调用的方法,然后稍后验证是否实际调用了该方法

您还可以让您的模拟对象拦截方法调用,并用自定义逻辑替换它。例如,您可以将调用
breakBlockAt
委托给修改
HashMap
而不是实际数据库的方法。然后,返回值的行为可能会有所不同,这取决于以前对
HashMap
所做的调用

当然,您还应该为您的
World
类提供一个单独的测试用例,以实际测试与数据库一起工作的逻辑(但不增加
Player
类的复杂性)。这基本上是一个集成测试,您可以在其中确保JDBC语句或JPA对象生成有效的SQL,当与您选择的数据库方言一起使用时,这些SQL可以正常工作。
类库可用于在单元测试中的Docker容器中设置空数据库。唯一的要求是您的测试环境运行Docker并准备好执行。

单元测试的思想是,在每个测试中,您只测试代码的一个组件

也就是说,在
World
的测试中,我会模拟数据库连接,并在
World.breakBlockAt(x,y,z)
上编写测试,在这里我模拟数据库来执行各种情况。
这里的想法不是测试数据库,而是:
-您的代码将正确的输入传递到数据库
-您的代码将按预期处理各种结果。
-代码正确处理来自db的所有类型的响应(例如,正确处理异常)


这一步同样适用于
Player
-在这一步中,您应该模拟世界,检查Player中的代码是否将正确的值传递给世界,并处理ok。它的响应取决于您希望执行的测试类型:

  • 单元测试:这旨在测试代码的单个“单元”,通常是类。在本例中,您只对正在测试的特定单元的行为感兴趣,因此模拟所有依赖项以模拟所需的行为
  • 集成测试:旨在测试多个单元之间的相互作用。因为您一次只对几个单元感兴趣,所以可以模拟任何不在特定集成测试中的模块
  • 功能测试:旨在测试应用程序的功能或用例。这涉及到对代码结构的更多抽象,因为您希望测试用户与应用程序的交互,而不是特定的代码单元。这种测试通常很少甚至没有模拟
请注意,模拟通常涉及使用模拟库(例如Mockito)来简化模拟

还要注意,如果使用依赖项注入,代码的可测试性会更好,因为您也可以注入模拟