Самый чистый способ "карри" бегущих - PullRequest
2 голосов
/ 17 апреля 2020

Я пишу тест 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 ]

4 голосов
/ 17 апреля 2020

Не поймите это неправильно: ваши текущие и желаемые подходы действительно трудно следовать.

Насколько я вижу, вы пытаетесь проверить Person для множества комбинации параметров.

Это явно не идиоматический c способ сделать это. Помимо всего прочего, вы должны быть очень осторожны, чтобы восстановить изменяемое состояние 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(...);
    }
  }
}
0 голосов
/ 17 апреля 2020

Сделав site переменной экземпляра, я смог удалить ее из подписей withX(). Это позволило мне связать их через

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