我正在为我的系统进行单元测试,但是我发现自己非常怀疑如何对相关的资源进行测试和验证逻辑,并且在这种关系中应该是唯一的。
例如,我有以下内容:
在同一项目中不能有两个具有相同名称的产品。仅当它们在同一个项目中时才适用,当它们在不同的项目中时,可能会有许多名称相同的产品。
我认为我应该将验证留给数据库,并等待系统中的异常,以便我的测试执行用例并等待异常,因此我将该验证应用于我的ProductRepositoryStub中,以模拟数据库会做。
另一方面,我想到要在用例中执行验证,在执行操作之前先对数据库查询进行验证,这样测试会更简单。
这实际上对应于单元测试,还是应该是集成测试?在我的系统中,我有很多类似的情况。
答案 0 :(得分:1)
我认为这个问题很好地说明了单元测试,集成测试所涉及的复杂性,以及它们之间的界限以及每种方法的有用性。
虽然没有“正确”的答案,但这就是我要做的。希望它能提供一些见解并帮助您找出最能满足您的需求的
将其留给数据库以检测重复是非常合理的-数据库擅长此事,并且减少了您必须编写的代码量。一个简单的唯一约束(产品名称,项目)就足够了。实际上,如果您对事务边界不是很谨慎的话,尝试在数据库约束以外的任何地方强制执行此操作(例如在写入之前在应用程序逻辑中进行读取然后进行验证)可能会导致争用情况。因此,鉴于使用数据库实施此约束是最好的方法,我们如何对其进行测试?
单元测试:我认为,如果可能的话,这里的单元测试是一个不错的选择。单元测试应该始终是基于test pyramid的首选。但是,您的单元测试不必测试数据库强制执行唯一约束的能力(这不在您要测试的“单元”的范围之内)。相反,您的单元测试应该断言,如果数据库由于唯一约束冲突而引发异常,则系统行为正确。是否需要在应用程序的任何层将该异常转换为自定义异常?如果是这样,请对该单元进行测试。由于原始或翻译后的异常,您的应用程序是否需要返回特定的HTTP状态代码?如果是这样,请对该单元进行测试。
集成测试::由于您依赖数据库来实施唯一约束,因此如果没有集成测试,就无法完全测试系统与数据库之间的交互将按预期进行。您可以在此处使用一些变体,并且必须确定哪种变体最适合您的用例。在某些Java应用程序中,将模式加载到内存中的H2数据库中并在数据库访问类和刚刚建立的测试数据库之间执行最小集成测试是一种相对常见的做法。其他人可能更喜欢端到端的集成测试方法,该方法涉及在真实数据库上运行您的应用程序,然后在该数据库上运行API测试。
您提到,您有许多与此案例类似的案例-因此请考虑哪种方法最适合测试所需的所有方案。端到端测试的不利之处在于,由于它们额外的依赖性,它们的启动速度可能较慢,管理起来也更加困难,这可能会使您的反馈周期更长。另一方面,它们提供了在稍微接近生产环境的条件下进行声明的能力。