java - 测试与外部服务的交互

标签 java unit-testing testing playframework

先决条件:我使用的是最新版本的 Play! framework ,以及 Java 版本(不是 Scala)。

我需要在创建用户时向消息队列发布一条消息,我想测试该行为。我的问题是让它易于测试。

Controller 方法

在其他框架中,我会做的是在 Controller 中使用构造函数注入(inject)并在我的测试中传入模拟队列;然而,随着游戏! Controller 是静态的,这意味着我无法在测试中执行 new MyController(mockedQueue)

我可以使用 Google Guice 并在我的 Controller 中的静态字段上放置一个 @Inject 注释,但这对我来说感觉不太好,因为这要么意味着我必须创建该字段public 在测试中被替换,或者我必须在我的测试中使用一个容器。我更喜欢使用构造函数注入(inject),但是玩!似乎并没有促进这一点。

模型方法

人们常说您的逻辑应该在您的模型中,而不是您的 Controller 中。这就说得通了;但是,我们这里不是在 Ruby 中,让您的实体与外部服务(电子邮件、消息队列等...)交互比在动态环境中可测试性要低得多,在动态环境中您可以替换 MessageQueue随意使用模拟实例进行静态调用。

如果我让我的实体调用队列,那如何测试?

当然,如果我进行端到端集成测试,这两种情况都是不必要的,但我宁愿不需要消息队列或 SMTP 服务器来运行我的测试。

所以我的问题是:我如何为我的 Play 建模! Controller 和/或模型以促进测试与外部服务的交互?

最佳答案

据我所知,对此没有一个干净的解决方案。

你可以使用 Abstract Factory为了你的依赖。这个工厂可以为它生产的对象提供 setter 方法。

public class MyController {
    ...
    private static ServiceFactory serviceFactory = ServiceFactory.getInstance();
    ...
    public static void action() {
        ...
        QueueService queue = serviceFactory.getQueueService();
        ...
    }

你的测试看起来像这样:

public void testAction() {
    QueueService mock = ...
    ...
    ServiceFactory serviceFactory = ServiceFactory.getInstance();
    serviceFactory.setQueueService(mock);
    ...
    MyController.action();
    verify(mock);
}

如果您不想公开工厂的 setter 方法,您可以创建一个接口(interface)并在测试中配置实现类。

另一种选择是使用 o PowerMock用于模拟静态方法。我以前用过,在大多数情况下效果都很好。只是不要过度使用它,否则您将陷入维护困境...

最后,既然您愿意在您的应用程序中使用 Guice,this可能是一个可行的选择。

祝你好运!

关于java - 测试与外部服务的交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7462843/

相关文章:

java - Android App Widget 广播不起作用

java - Wasabi自动重启docker容器

java - 在 App Engine 中存储 BitSet

C++ 与性能指标的持续集成

ruby-on-rails - Rspec/Rails3 : NoMethodError: undefined method `text' for nil:NilClass

java - 在仪器测试期间将大写字母发送到 TextEdit

java - 我的 java 求幂语法是否错误?

unit-testing - 如何进行仅在断言失败时通过的测试?

python - 单元测试包 Maven 风格约定

javascript - 运行时设置 puppeteer 窗口大小而不是 headless (不是视口(viewport))