【问题标题】:What is the best way to mock DTOs in Java?在 Java 中模拟 DTO 的最佳方法是什么?
【发布时间】:2012-09-17 07:31:26
【问题描述】:

在编写单元测试时,我需要一些带有示例数据的对象。例如,假设我有一个 Order 对象。需要编写这样的代码 -

Order o = new Order();
o.setId(3);
o.setAmount(2830.9);

List<Item> items = new ArrayList<Item>();
Item i = new Item();
i.setId(3);
i.setCost(34);
items.add(i);

o.setItems(items);

它比这里看起来更令人沮丧和多余,因为一个真实的对象可能有更多的属性和嵌套的对象。

如果一个人需要多个订单...

创建用于测试的模拟数据对象的最佳方法是什么?

我正在考虑从 Json 反序列化我的对象。有没有标准、有效的方法来做到这一点?

【问题讨论】:

  • 也许你可以看看 Mockito。
  • 我建议看看github.com/nomemory/mockneat。这是一个专门用任意数据模拟 DTO 对象的库,

标签: java unit-testing mocking dto


【解决方案1】:

通常 DTO 只包含字段,没有需要模拟的逻辑。

我会使用 DTO 作为其自身的模拟。如果 DTO 中包含您可能想模拟的逻辑,我会将逻辑移出 DTO。

要创建 DTO,我会从文本中执行此操作,无论是在测试本身中,还是从外部文件中。您可以使用 JSON,但如果您不使用它,我将使用 XMLEncoder/XMLDecoder。它不是漂亮的 XML,但它是内置的,因此您不需要额外的库。

如果可以,您或许可以从应用程序的日志中创建 DTO,这样您就可以重新创建一个真实的场景。

【讨论】:

    【解决方案2】:

    另一种方法可能是为属性生成随机值。

    PODAMopenpojo 之类的实用程序可以提供帮助。

    我会尽量混合使用这两种方法。比如——用PODAM生成对象,然后手动设置不能随机的值。

    【讨论】:

      【解决方案3】:

      模拟框架通常不鼓励模拟数据对象。

      但是每次在测试中需要数据对象时填充数据对象可能会很不方便。

      一种常见的方法是使用测试构建器。比如:

      public class MyDtoBuilder {
      
         private Foo foo;
         private Bar bar;
      
         public static MyDtoBuilder aMyDto() {
             return new MyDtoBuilder();
         }
      
         public MyDtoBuilder withFoo(Foo foo) {
             this.foo = foo;
             return this;
         }
      
         public MyDtoBuilder withBar(Bar bar) {
             this.bar = bar;
             return this;
         }
      
         public MyDtoBuilder withDefaults() {
             return this.withFoo(new Foo(...)).withBar(new Bar(...));
         }
      
         public MyDto build() {
             return new MyDto(foo,bar);
         }
      }
      

      现在您可以方便地使用默认值构建 DTO,然后根据需要覆盖它们。如果FooBar 很复杂,您也可以为它们配备测试构建器,这样您就可以做类似

        MyDto expectedDto = aMyDto()
            .withDefaults()
            .withFoo(aFoo()
                .withName("testFoo"))
            .build();
      

      Freeman 和 Pryce 所著的Growing Object-Oriented Software一书中详细介绍了这一点。

      您应该注意区分测试构建器和用于非测试代码的构建器(这是实例化不可变对象的常见模式)。不要跨越这些流——不要在非测试代码中使用您的测试构建器。

      【讨论】:

      • 也很郁闷
      【解决方案4】:

      对于具有不同值的多个对象,我会采用 Peter Lawreys 的建议,但对于始终具有相同值的单个 DTO,我会创建一个始终返回相同值的模拟。

      【讨论】:

        猜你喜欢
        • 2013-10-30
        • 2013-08-05
        • 2010-11-20
        • 1970-01-01
        • 2020-02-03
        • 1970-01-01
        • 2012-01-09
        • 1970-01-01
        • 2013-11-25
        相关资源
        最近更新 更多