【问题标题】:How to test arguments passed to constructor on a factory method?如何在工厂方法上测试传递给构造函数的参数?
【发布时间】:2015-04-16 10:52:52
【问题描述】:

我遇到了一个我真的不知道如何解决的情况。我刚刚创建了一个类 Foo ,其中包含一个静态工厂方法来使用一些参数创建类 Bar ,因此 Foo 是一种工厂类。现在我想测试这个方法,但问题是,这些参数在内部被修改以创建在 Bar 上调用构造函数所需的变量。作为测试的一部分,我可以测试我得到 Bar 的最终对象,但我不知道如何验证传递给构造函数的参数。

public class Foo {
      public Bar createBarOf(String argumentOne, String argumentTwo) {
             String argumentForBar = argumentOne + argumentTwo;
             return new Bar(argumentForBar);
      }
}

有什么建议吗?

编辑

为了让问题更清楚,这是 Bar 类。

    public class Bar {
          private final String SUFFIX = "BarSuffix";
          private String field;

          public Bar(String argumentForBar) {
                field = argumentForBar + BAR_SUFFIX;
          }
    }

所以,考虑到构造函数。当我在 Foo 中测试 createBarFor(argumentOne,argumentTwo) 时,我无法弄清楚如何测试用于创建 Bar 的 argumentOne 和 argumentTwo,除非我还在该测试中测试 Bar 构造函数并假设 Bar 的内部结构是什么。 argumentOne 和 argumentTwo 不是 Bar 的存储字段,而是用于计算对象中字段值的变量。

【问题讨论】:

    标签: java oop junit


    【解决方案1】:

    只需使用 createBarOf 并针对返回的 Bar 对象声明您的期望。当您使用参数ab 创建构造函数时,您不应该试图断言ab 已传递给构造函数,当您获得Bar 对象时已经包含这些参数。

    由于createBarOf 内部没有退出逻辑(从方法返回的执行分支),因此您无需专门测试有关此方法的任何内容。

    【讨论】:

    • 但是我不应该在 Bar 类的特定单元测试中测试我的期望吗?测试 Bar 作为 Foo 测试的一部分将使 Bar 的单元测试变得多余(至少对于它的构造函数而言)。我可以在这里测试工厂方法和 Bar 构造函数,但是 Bar 的单元测试不包括对其构造函数的测试似乎很奇怪。而且仅仅测试我从工厂方法中获得了一个 Bar 类型的对象并不能确保为构造函数创建参数的逻辑(实际代码比连接两个字符串要复杂一些)
    • @Kilian:我不是说你测试你收到了一个 Bar 对象。我的意思是你对返回的 Bar 对象执行你的断言;这个论点有什么影响?它会改变一些变量吗?然后断言Bar.getArgument()。您的单元测试可以包含多个分层单元:看看我的答案stackoverflow.com/a/17731324/1864167
    • 我遇到的问题是传递的参数从未存储在 Bar 对象中。它在构造函数中用于填充其他对象的列表。我的问题是,没有 Bar.getArgumentForBar() 而是 Bar.getNewCalculatedValue() 。如果我想验证 Foo 工厂方法是否使用传递的参数,除非有办法在单元测试中捕获这些参数,否则我还必须在 Bar 中测试构造函数逻辑,我想在单元测试中这样做专门针对它。
    • 对,但你仍然没有展示它是如何使用的。只需测试最终使用field 的代码,看看它是否完美。它隐含地测试了这一点。
    • 好的,所以您是说测试工厂方法的唯一方法是在应用构造函数中的逻辑后验证field 是否包含预期数据。我之所以问这个问题是因为在我看来,field 的使用方式或它包含的内容并不重要。测试应该只验证为构造函数训练参数的逻辑,而不是构造函数本身。这应该是 Bar 单元测试的一部分,而不是 Foo 单元测试的一部分。但如果没有办法做到这一点,那么我应该得到field 并断言它是有道理的,所以构造函数也在这里进行测试。
    【解决方案2】:

    我也遇到过类似的情况。如果你的 Bar 有一个 equals 方法,你总是可以构建你期望工厂在你的测试中构建的 Bar 并且......

    assertThat(actualbar).isEqualTo(expectedBar)
    

    但是,如果“等于”没有任何意义,或者由于任何原因您无法更改“Bar”,那么除了使用反射来获取 Bar 的私有字段之外,您可能别无选择看看是否设置了正确的值。

    例如(这使用了一个名为 ReflectionTestUtils 的“spring-test”类)...

    assertThat(ReflectionTestUtils.getField(actualBar, "argumentForBar")).isEqualTo(expectedValue);
    

    【讨论】:

    • 正如对上一个回复的评论,在 Bar 的特定单元测试中测试构造函数对我来说更有意义,而不是将其作为 Foo 中工厂方法测试的一部分。对我来说,这里应该测试的是为 Bar 构造函数创建最终参数的逻辑,而不是构造函数的工作方式(应该是另一个测试)。但是如果没有其他办法,我想我将不得不测试这里调用构造函数的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-10
    • 1970-01-01
    • 2012-08-29
    • 2017-01-31
    • 1970-01-01
    • 2017-07-30
    • 2019-05-21
    相关资源
    最近更新 更多