3 回答
TA贡献1998条经验 获得超6个赞
正如 deHaar 在他的评论中指出的那样,您想要涵盖许多边缘情况。在测试数据库时,可以执行以下操作:
您模拟数据库(在您的存储库中的 Spring 项目中),并将其配置为返回/抛出。然后在您的测试中,您测试以下内容:
givenNoCustomerInDB_thenNotFoundExceptionThrownIsWrappedToXXX()
. 在这里,您将测试调用数据库的服务方法是否捕获异常并相应地包装它。对于这种方法,您可能需要查找 Mockito,它是 Java 的“事实上的”模拟框架。另一种选择是在进行测试时使用内存数据库(例如 H2)。
要记住的一件事:您有责任确保模拟(或 H2)表现得像您的真实数据库。@Kraylog 建议将适配器写入 IO 设备的集成测试,以及确保模拟行为相同的合同测试。
TA贡献1801条经验 获得超8个赞
首先,虽然大多数函数都可以进行测试,但并非所有函数都需要直接测试。通过调用代码的测试可以更好地测试一些。
其次,在处理依赖于状态的副作用或代码时,有一些方法可以创建测试特定场景所需的上下文。其中一种方法是使用test doubles。
当然,我们需要对不是纯函数的代码进行测试。您可以尽量减少非纯函数的代码量(例如使用函数式编程),但如果您不这样做,那么您的其余代码也需要进行测试。
最后,您所说的“比率”或通常所说的“测试覆盖率”取决于您对测试套件的信心水平。最后,正是这种信心使您可以重构代码而不必担心破坏事物,这最终才是重点。
TA贡献1852条经验 获得超7个赞
在将测试对象与其通常环境隔离的测试中,您会input -> logic -> output经常看到这种模式,因为输入数据必须由环境提供,而测试是对象所经历的环境。
TDD经常使用孤立的测试;它们通常既快速又令人尴尬地并行,这意味着在设计阶段运行它们具有较低的机会成本。
String getName (int id)
{
// read the name of a staffmember out of the DB and return it
}
在像这样的示例中,我们通常会被驱使设计“该”数据库是可配置的,并且在我们的测试中,我们将提供预加载到正确状态的内存数据库。
// Copy input to database
// connect test subject to database
// invoke query, thereby retrieving the output
是一样的图案,只是雕刻的不同。
在许多情况下,我们可以在我们的设计中为数据库引入一些抽象,并使该抽象而不是数据库成为配置的依赖项。因此,与其使用与数据库对话的抽象,不如使用更简单的实现,通过硬编码来返回一些值。
这样的事情有时被称为测试替身。
// Use the input to initialize the test double
// connect test subject to test double
// invoke query, thereby retrieving the output
同样的模式再次出现,“逻辑”的细节发生了一些变化。
logicofinput -> logic -> output不一定是您的生产代码。编写与一个外观集成的测试是很常见的,该外观协调测试主体与其(双重)依赖关系之间的交互协议。
(测试,就像生产代码一样,有设计——现在投资一个好的设计可能会在测试的整个生命周期内产生可观的利润)。
添加回答
举报