清除“ curry”可运行对象的最干净方法

时间:2020-04-17 14:46:02

标签: java junit runnable currying

我正在编写一个JUnit测试,并且想要在对象具有几个不同变量的地方运行测试。我通过传递可运行对象来避免深层嵌套的循环。

private Runnable withAges( final Person person, final Runnable r ) {
    return () -> {
        person.setAge( 0 );
        r.run();
        person.setAge( 50 );
        r.run();
        person.setAge( Integer.MAX_VALUE );
        r.run();
        person.setAge( -1 );
        r.run();
        person.setAge( Integer.MIN_VALUE );
        r.run();
    };
}

private Runnable withHair( final Person person, final Runnable r ) {
    return () -> {
        person.setHair( "blonde" );
        r.run();
        person.setHair( "BLONDE" );
        r.run();
        person.setHair( null );
        r.run();
    };
}

private Runnable withAddresses( final Person person, final Runnable r ) {
    ...
}

private Runnable withChildren( final Person person, final Runnable r ) {
    ...
}

实际测试为:

@Test
void testPerson() {
    final Person person = new Person();
    final Runnable tests = () -> {
        assertTrue( ... );
        assertFalse( ... );
    }
    ...
}

当前,我可以使用

运行这些测试
withAges( person,
          withHair( person,
                    withAddresses( person,
                                   withChildren( person, tests ) ) ) );

但是,如果我能通过写类似的东西来清理它

withAges( person ).withHair( person ).withAddresses( person ).withChildren( person ).tests.run();

2 个答案:

答案 0 :(得分:4)

请不要用这种错误的方式:您当前和期望的方法都很难遵循。

据我所知,您正在尝试测试Person的一系列参数组合。

这是一种明显的非惯用的方式。除了任何事情,您还必须非常小心地恢复Person的可变状态,以免干扰测试之间。

您可能会找到类似JUnit Theories的方法,这是一种更简单的方法:

@DataPoints("ages") Set<Integer> ages = Set.of(0, 50, Integer.MIN_VALUE, -1 /* etc */);
@DataPoints("hairs") Set<String> hairs = Set.of("blonde", "BLONDE" /* etc */);
/* etc */

@Theory
public void testSomething(
    @FromDataPoints("ages") Integer age, @FromDataPoints("hairs") String hair) {
  Person person = new Person();
  person.setAge(age);
  person.setHair(hair);

  assertTrue(...);
  assertFalse(...);
}

即使这样,也更容易理解(尽管它在同一个测试用例中测试了多个项目,但有些人对此并不满意):

@Test
public void testSomething() {
  for (int age : Set.of(...)) {
    for (String hair : Set.of(...)) {
      Person person = new Person();
      person.setAge(age);
      person.setHair(hair);

      assertTrue(...);
      assertFalse(...);
    }
  }
}

答案 1 :(得分:0)

通过使site为实例变量,我能够将其从withX()签名中删除。这使我可以通过

链接它们
withAges( withHair( withAddresses( withChildren( tests ) ) ) ).run()