【问题标题】:How to test code which mostly uses external APIs?如何测试主要使用外部 API 的代码?
【发布时间】:2020-10-11 08:19:11
【问题描述】:

我最近编写了一些代码,发现几乎不可能编写有用的测试。

这是一个定时任务:

  • 从外部服务 (AWS cognito) 获取用户
  • 通过询问我们系统的内部 API 来检查用户的某些属性
  • 根据业务逻辑向用户发送邮件(AWS SES)
  • 更新用户属性 (AWS cognito)

总共大约 100 行 python。为了测试这一点,通常的建议似乎是检查 API 的格式并在测试中模拟它们。我可以为我的“快乐之路”这样做,但我真的没有办法知道在所有情况和故障模式下数据将如何传输,因为涉及的外部服务太多。

如果收到一些意外的数据,我预计这段代码会失败,但没有办法对此进行测试,或者有吗?

我已经在一个更大的系统中使用 pact 进行了消费者驱动的合同测试,但在这里我只能针对我们控制的内部 API 使用它,而对于这样一个小系统来说,所需的基础设施似乎太多了脚本。

我们目前的方法是监控脚本中的错误,并在第二天在办公室进行修复。从业务规则的角度来看,如果脚本几天不运行,这不是问题。您认为这是最好的方法吗?

你会如何测试这个?

【问题讨论】:

    标签: api unit-testing testing integration-testing


    【解决方案1】:

    tldr;根据资源、优先级和关键性解决方案以及监控和一些单元测试可能是一个不错的选择。


    在这种情况下,我会尝试解耦组件。它将允许我独立测试所有组件并简化最终测试逻辑。

    让我们从示例中考虑 cronjob。可能伪代码看起来像下一个:

    def main():
        users: List[Users] = fetch_users()
        filtered_users = check_properties(users)
    
        business_logic_with_sending_emails(filtered_users)
        update_properties(filtered_users)
    

    我在单独的函数上划分逻辑,现在我可以单独测试每个函数(甚至是主函数)

    fetch_users 负责与外部系统交互并将其响应转换为预定义的用户模型。如果发生任何错误,fetch_users 应该处理它。根据外部系统,我可以使用集成测试或使用模拟/存根的单元测试来测试此功能。每个选项都有自己的优点和缺点。你提到你有监控和功能并不重要,所以带有模拟/存根的单元测试和监控将是一个很好的选择。即使我们在模拟测试中错过了一些负面场景并且它在生产中失败,监控也会捕获它,使用单独的fetch_users 函数我们可以本地化和重现它,然后我们可以轻松地使用这个新案例扩展我们的测试。

    使用check_properties,我们可以做同样的事情——使用集成测试或模拟/存根测试它。这里主要是我们不需要调用fetch_users,我们可以直接将测试用户转移到check_properties。正如你提到的check_properties 调用内部 api,所以我们可以在这里使用消费者驱动的合同测试(如果它已经存在),或者集成测试或任何其他保证系统之间合同的测试(即通过 swagger/openapi 规范进行验证)

    business_logic_with_sending_emails — 从业务的角度来看,这个功能可能是最重要的,所以我们需要用单元(func)测试来覆盖所有的业务逻辑。幸运的是,我们不需要向任何真实的外部系统发出请求(获取用户),我们只需将测试用户直接转移到business_logic_with_sending_emails。我们甚至不需要检查真实的电子邮件发送,检查我们调用了发送电子邮件的函数就足够了(发送真实的电子邮件我们可以在单独的集成测试中检查) update_propertiesfetch_users 的故事相同。

    最后一个是main。虽然我们分别测试了所有函数,但不能保证 main 中的所有函数都被正确调用。可能在示例伪代码这样简单的函数中,不需要对其进行测试(因为没有任何复杂的逻辑),但在复杂的情况下,最好检查“快乐路径”并且很少有负面影响。它可以通过模拟或 IoC/DI 机制来完成。

    【讨论】:

    • 感谢您的广泛回答。我也倾向于这样的解决方案,但它仍然需要相当多的模拟,并且在服务发送意外数据的情况下仍然会出现运行时错误。因此,似乎没有一种方法可以更接近于在单体应用中进行测试所获得的信心。
    猜你喜欢
    • 1970-01-01
    • 2021-04-12
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-15
    • 2011-10-08
    • 2016-04-27
    相关资源
    最近更新 更多