如何测试主要使用外部API的代码?
我最近写了一些代码,发现编写有用的测试几乎是不可能的 这是一个cronjob,它实现了以下功能:如何测试主要使用外部API的代码?,api,unit-testing,testing,integration-testing,Api,Unit Testing,Testing,Integration Testing,我最近写了一些代码,发现编写有用的测试几乎是不可能的 这是一个cronjob,它实现了以下功能: 从外部服务(AWS cognito)获取用户 通过询问系统的内部API来检查用户的某些属性 根据业务逻辑向用户发送邮件(AWS SES) 更新用户属性(AWS cognito) 总共大约有100行python代码。为了测试这一点,通常的建议似乎是检查API的格式并在测试中模拟它们。我可以为我的“快乐之路”这样做,但我真的没有办法知道在所有情况下和故障模式下数据将如何传输,因为涉及到这么多外部服务
- 从外部服务(AWS cognito)获取用户
- 通过询问系统的内部API来检查用户的某些属性
- 根据业务逻辑向用户发送邮件(AWS SES)
- 更新用户属性(AWS cognito)
您将如何测试这一点?tldr;根据资源、优先级和关键性解决方案,监控和一些单元测试可能是一个很好的选择
在这种情况下,我会尝试解耦组件。它将允许我独立测试所有组件,并简化最终测试逻辑 我们从例子中考虑Cron Joobe。伪代码可能与下一个类似:
def main():
用户:列表[用户]=获取用户()
过滤的\u用户=检查\u属性(用户)
业务逻辑发送电子邮件(过滤用户)
更新\u属性(筛选的\u用户)
我将逻辑划分为不同的函数,现在我可以分别测试每个函数(甚至是main)
fetch_用户
负责与外部系统交互,并将其响应转换为预定义的用户模型。如果出现任何错误,fetch\u用户应处理该错误。根据外部系统的不同,我可以使用集成测试或使用模拟/存根的单元测试来测试此功能。每种选择都有其优缺点。您提到您有监控功能,并且功能并不重要,因此使用mock/stub和监控的单元测试将非常适合。即使我们在模拟测试中错过了一些负面场景,并且在生产中失败了,监控也会捕捉到它,通过一个单独的fetch\u users
函数,我们可以对其进行本地化和复制,然后我们可以轻松地用这个新案例扩展我们的测试
使用check_properties
我们也可以做同样的事情——用integ测试或mock/stub测试它。这里最重要的是,我们不需要调用fetch\u users
,我们可以将测试用户直接转移到check\u properties
。正如您所提到的check\u properties
调用内部api,因此我们可以在这里使用消费者驱动的契约测试(如果已经存在),或integ测试或任何其他保证系统之间契约的测试(即通过swagger/openapi规范进行验证)
business\u logic\u发送电子邮件
-从业务的角度来看,这个功能可能是最重要的,所以我们需要用单元(func)测试覆盖所有业务逻辑。幸运的是,我们不需要向任何真正的外部系统发出请求(获取用户),我们只需通过发送电子邮件将测试用户直接传输到业务逻辑。我们甚至不需要检查真正的电子邮件发送,只需检查我们调用发送电子邮件的函数(发送真正的电子邮件,我们可以在单独的集成测试中检查)
使用update\u属性
与使用fetch\u用户
的情况相同
最后一个是main
。虽然我们单独测试了所有函数,但不能保证main中的所有函数都被正确调用。在像示例伪代码这样简单的函数中,可能不需要对其进行测试(因为没有任何复杂的逻辑),但在复杂的情况下,最好检查“快乐路径”和少量的负面代码。它可以用mock或IoC/DI机制来完成。tldr;根据资源、优先级和关键性解决方案,监控和一些单元测试可能是一个很好的选择
在这种情况下,我会尝试解耦组件。它将允许我独立测试所有组件,并简化最终测试逻辑
我们从例子中考虑Cron Joobe。伪代码可能与下一个类似:
def main():
用户:列表[用户]=获取用户()
过滤的\u用户=检查\u属性(用户)
业务逻辑发送电子邮件(过滤用户)
更新\u属性(筛选的\u用户)
我将逻辑划分为不同的函数,现在我可以分别测试每个函数(甚至是main)
fetch_用户
负责与外部系统交互,并将其响应转换为预定义的用户模型。如果出现任何错误,fetch\u用户应处理该错误。根据外部系统的不同,我可以使用集成测试或使用模拟/存根的单元测试来测试此功能。每种选择都有其优缺点。您提到您有监控功能,并且功能并不重要,因此使用mock/stub和监控的单元测试将非常适合。即使我们在模拟测试中错过了一些负面场景,并且在生产中失败了,监控也会捕捉到它,通过一个单独的fetch\u users
函数,我们可以对其进行本地化和复制,然后我们可以轻松地用这个新案例扩展我们的测试
使用检查属性
我们可以