Java 模块化应用程序堆栈中的虚拟数据和单元测试策略
如何管理用于测试的虚拟数据?将它们保存在各自的实体中?在单独的测试项目中?从外部资源用序列化程序加载它们?或者只是在需要的地方重新创建它们 我们有一个包含多个模块的应用程序堆栈,每个模块依赖于另一个模块,每个模块都包含实体。每个模块都有自己的测试,需要虚拟数据来运行 现在,一个具有大量依赖项的模块将需要来自其他模块的大量虚拟数据。但是,这些模块不会发布它们的虚拟对象,因为它们是测试资源的一部分,所以所有模块都必须一次又一次地设置它们需要的所有虚拟对象 另外:我们实体中的大多数字段都不可为空,因此即使在对象层上运行事务也需要它们包含一些值,大多数情况下还存在其他限制,如唯一性、长度等 是否有一种最佳实践方法可以解决这个问题,或者所有解决方案都是折衷方案Java 模块化应用程序堆栈中的虚拟数据和单元测试策略,java,unit-testing,testing,maven,modular,Java,Unit Testing,Testing,Maven,Modular,如何管理用于测试的虚拟数据?将它们保存在各自的实体中?在单独的测试项目中?从外部资源用序列化程序加载它们?或者只是在需要的地方重新创建它们 我们有一个包含多个模块的应用程序堆栈,每个模块依赖于另一个模块,每个模块都包含实体。每个模块都有自己的测试,需要虚拟数据来运行 现在,一个具有大量依赖项的模块将需要来自其他模块的大量虚拟数据。但是,这些模块不会发布它们的虚拟对象,因为它们是测试资源的一部分,所以所有模块都必须一次又一次地设置它们需要的所有虚拟对象 另外:我们实体中的大多数字段都不可为空,因此
更多细节 我们的堆栈如下所示: 一个模块:
src/main/java --> gets jared (.../entities/*.java contains the entities)
src/main/resources --> gets jared
src/test/java --> contains dummy object setup, will NOT get jared
src/test/resources --> not jared
我们使用Maven来处理依赖关系
模块示例:
- 模块A有一些虚拟对象
- 模块B需要自己的对象,与模块A相同
src/main/java../entities/dummy
中的某处提供虚拟对象,允许B获取它们,而A不知道B的虚拟数据
选项c)
每个模块都包含作为序列化虚拟对象的外部资源。它们可以由需要它们的测试环境反序列化,因为它依赖于它们所属的模块。这将要求每个模块创建并序列化它的虚拟对象,而我们将如何做到这一点?如果使用另一个单元测试,它会在单元测试之间引入不应该发生的依赖关系,或者使用脚本,那么调试将很困难,也不灵活
选项d)
使用模拟框架,并根据需要为每个测试手动分配所需字段。这里的问题是,实体中的大多数字段都不可为空,因此需要调用setter或constructor,这将导致我们再次开始
我们不想要的
我们不想用静态数据建立静态数据库,因为所需对象的结构将不断变化。现在很多,晚一点。因此,我们希望hibernate设置所有表和列,并在单元测试时用数据填充这些表和列。此外,静态数据库会引入许多潜在错误和测试相关性
我的想法正确吗?处理需要大量数据的测试的最佳实践是什么?我们将有几个相互依赖的模块,这些模块需要对象填充来自其他几个模块的某种数据
编辑 关于第二个答案,我们现在如何做的更多信息: 为了简单起见,我们有三个模块:
人
,产品
,订单
。
Person
将使用MockPerson
对象测试一些管理器方法:
(亲自/src/test/java:)
不会打包MockPerson
类
同样适用于产品测试:
(在product/src/test/java:)
MockProduct
是必需的,但不会打包
现在,订单测试将需要MockPerson
和MockProduct
,因此现在我们需要创建这两个组件以及MockOrder
来测试订单
(顺序为/src/test/java:)
这些是重复的,需要在每次人员
或产品
更改时进行更改
public class MockProduct() { ... }
public class MockPerson() { ... }
这是唯一应该在这里的类:
public class MockOrder() { ... }
public class TestOrder() {
@Inject
private order.MockPerson mockPerson;
@Inject
private order.MockProduct mockProduct;
@Inject
private order.MockOrder mockOrder;
public testCreate() {
Order order = mockOrder.mockOrder(mockPerson.mockPerson(), mockProduct.mockProduct());
// Asserts...
}
}
问题是,现在我们必须在person
发生更改时更新person.MockPerson
和order.MockPerson
用jar发布Mock不是更好吗?这样其他所有具有依赖关系的测试都可以调用Mock.Mock并获得一个很好的设置对象?或者这是黑暗的一面-简单的方法?这可能适用,也可能不适用-我很想看看您的虚拟对象和相关设置代码的示例。(为了更好地了解它是否适用于您的情况。)但我过去所做的工作甚至没有在测试中引入此类代码。正如您所描述的,它很难生成、调试,尤其是打包和维护 我所做的(Java中的AFAIKT是最佳实践)是尝试使用TestDataBuilder模式,正如在他的文章中所描述的 如果您认为这有点相关,请查看以下内容:
- ,实现此模式的Nat框架
public class MockProduct() { ... }
public class MockPerson() { ... }
public class MockOrder() { ... }
public class TestOrder() {
@Inject
private order.MockPerson mockPerson;
@Inject
private order.MockProduct mockProduct;
@Inject
private order.MockOrder mockOrder;
public testCreate() {
Order order = mockOrder.mockOrder(mockPerson.mockPerson(), mockProduct.mockProduct());
// Asserts...
}
}