【问题标题】:Dropwizard Integrated Testing with Mocks for DBDropwizard 使用 Mocks for DB 进行集成测试
【发布时间】:2015-05-06 14:26:19
【问题描述】:

首先:是的,我读到了这个https://dropwizard.github.io/dropwizard/manual/testing.html

我想做一些集成测试,并说明为什么我必须启动整个应用程序。现在的问题是,我有一些与“外部世界”的接口,比如 DB 或一个内部 Rest-Client,它与一个远程应用程序交谈。我想用 mockito 来嘲笑他们。通常没问题。

现在我的问题是:如何使用模拟数据库和模拟客户端启动整个应用程序?

目前的问题是,我通过 getDBClient() 从我的配置类中获取了这个数据库连接和客户端......我不愿意在我的配置中构建一些测试代码,因为它的生产代码。因此,如果我通过 DropwizardAppRule 启动整个应用程序,该应用程序会尝试连接到数据库,但在测试环境中,没有可用的数据库。

有没有简单的说法:启动我的应用程序,但如果您调用 DB 或客户端,则使用此 XY 模拟?

我尝试过的: 一个新类“ExtendedService extends Service extends Application”和一个“ExtServiceConfiguration extends ServiceConfiguration”,但没有任何成功。但是如果我在返回模拟的配置类中覆盖一些方法,我会遇到麻烦。它并不适合所有在一起。

目前我阅读了 mockito spy 的文档,也许这会有所帮助,但我不确定如何在 DW 集成测试中使用它。我现在尝试模拟我的 2 个配置类方法以返回数据库和客户端模拟。也许有人可以帮助我,如何在下一个示例代码中模拟 TestConfiguration:

@ClassRule
public static final DropwizardAppRule<TestConfiguration> RULE =
        new DropwizardAppRule<TestConfiguration>(MyApp.class, resourceFilePath("my-app-config.yaml"));

编辑: @ClassRule public static final DropwizardAppRule RULE = new DropwizardAppRule(.....)

在@BeforeClass 中,我执行以下操作:

ServiceConfiguration oldConfig = RULE.getConfiguration();
ServiceConfiguration spy = Mockito.spy(oldConfig);
//Then DB mocking
IDatabaseLayer dBMock = mock(IDatabaseLayer.class);
Mockito.when(dBMock.isConnected()).thenReturn(true);
... // other mocking functions for DB
//this is important, it say, that the mocked config class should use the mocked DB
Mockito.doReturn(dBMock).when(spy).getDataBaseLayer(); // my configuration class has this method, so mocking config class with last created dbMock
// do other mockings if needed

这就是我启动整个应用程序所做的一切。

【问题讨论】:

  • 您能否发布到目前为止您的测试代码。我想看看您是如何尝试在您的测试中运行您的应用程序的,因为将您编写的内容拼凑起来有点挑战性。
  • 我想我终于做到了,我将在上面编辑我的帖子

标签: testing junit mockito dropwizard


【解决方案1】:

如果你真的想运行集成测试,我建议使用内存或临时数据库,如h2sqlite,如果可以的话,通过使用相关设置创建一个新的 yml 文件;并使用模拟的 http 服务,例如 Wiremock

否则按照 th3morg 的建议坚持ResourceTestRules。

【讨论】:

  • 我还必须模拟一些其他的东西,这就是问题所在。
  • DropwizardAppRule 几乎只用于闭箱测试。我认为没有任何其他测试课程可以帮助您完成您想做的事情。我将发布另一个答案,因为在评论部分很难解释。
【解决方案2】:

如果你想模拟特定的东西但仍然保持 dropwizard 的整个流程,那么你需要管理你自己的 Application 实例,并可以将你的依赖项注入到你的 Application 类中。因为DropwizardAppRule 没有给你那种灵活性。

示例:您希望能够覆盖对应用程序类的依赖项。

public class MyApplication extends Application {

  private FooManager fooManager;

  // Need to leave an empty constructor for other uses
  public MyApplication(){
  }

  public MyApplication(FooManager fooManager){
    this.fooManager = fooManager;
  }

  @Override
  public void run(Configuration configuration, Environment environment) throws Exception {
    if(fooManager == null){
      fooManager = new FooManagerImpl();
    }
    // stuff
  }
}

然后在你的测试中,你创建你自己的实例(或者你可以通过复制和修改DropwizardAppRule源代码来创建一个规则类。编辑:看起来你可以继承DropwizardTestSupport类和覆盖public Application&lt;C&gt; newApplication().)。

  @Test
  public void test(){
    FooManager fooManager = mock(FooManager.class);
    MyApplication myApplication = new MyApplication(fooManager);
    myApplication.run("server", "config.yml");
  }

【讨论】:

    【解决方案3】:

    我认为您应该改用 io.dropwizard.testing.junit.ResourceTestRule,它用于测试 Jersey 资源(即调用您的 REST API 端点)。 DropwizardAppRule 将启动整个应用程序并在测试结束时停止它。该课程似乎旨在用于端到端测试,您不会在其中进行任何模拟。

    【讨论】:

    • 你是对的资源测试规则。我已经在使用 ResourceTestRule 测试我的资源,但我有一些组件必须使用集成测试进行测试,因为我需要知道开始停止整个应用程序的行为如何。所以我必须启动整个应用程序,但我不想使用数据库,但这被我的组件重用了。这就是为什么我需要一个 DB-Mock 来进行集成测试。
    猜你喜欢
    • 2017-12-19
    • 1970-01-01
    • 1970-01-01
    • 2015-02-12
    • 2016-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多