передача статического метода в качестве параметра в Java - PullRequest
6 голосов
/ 13 марта 2019

Здравствуйте, я тестирую класс, в котором есть несколько проверяющих методов, и мне было интересно, есть ли способ уменьшить дублирующийся код.

@Test
void testCorrectEmailValidator() {
    List<String> correctEmails = Arrays.asList("test@test.com", "test123@test123.com", "test@test.com.in",
            "test.test2@test.com", "test.test2.test3@test.com", "TEST.2test@test.com");

    for (String email : correctEmails) {
        boolean isValid = UserCredentialsValidator.emailValidator(email);
        System.out.println("Email is valid: " + email + ": " + isValid);
        assertTrue(isValid);
    }
}

@Test
void testCorrectUsernameValidator() {
    List<String> correctUsernames = Arrays.asList("username", "123username", "username3", "user2name",
            "USERNAME", "USERNAME123", "123USERNAME123", "2uSERname33");

    for(String username : correctUsernames) {
        boolean isValid = UserCredentialsValidator.usernameValidation(username, userList);
        System.out.println("Username is valid:    " + username + "     : " + isValid);
        assertTrue(isValid);
    }
}

У меня также есть валидаторы для других полей, таких как имя пользователя и т. Д. Я думал о реализации вспомогательного метода, который бы принимал: проверенные учетные данные как String, List, но у меня проблема с последним параметром - проверяющим методом, не уверен как пройти это.

Код, который я хотел бы заменить каким-либо методом, это цикл for.

Ответы [ 4 ]

4 голосов
/ 13 марта 2019

Боюсь, ваши тесты низкого качества.

Проблемы, которые должны быть немедленно устранены, включают

  1. UserCredentialsValidator.usernameValidation(username, userList); Метод не должен принимать второй аргумент. Место, откуда берется этот список, должно быть скрыто от потребителя API.

  2. List<String> correctEmails = Arrays.asList(...) и List<String> correctUsernames = Arrays.asList(...) должны быть удалены. Лучше сделать параметризацию тестов с @ParameterizedTest и @ValueSource.

  3. Я бы предпочел удалить операторы System.out.println. Они не имеют большого смысла в тестах.


@ParameterizedTest
@ValueSource(strings = {"test@test.com", "test123@test123.com"})
void testUserEmailValidationWithValidUserEmailShouldPass(String validUserEmail) {
    boolean isValid = UserCredentialsValidator.emailValidator(validUserEmail);
    assertTrue(isValid);
}

@ParameterizedTest
@ValueSource(strings = {"username", "123username"})
void testUserNameValidationWithValidUserNameShouldPass(String validUserName) {
    boolean isValid = UserCredentialsValidator.usernameValidation(validUserName);
    assertTrue(isValid);
}

Теперь уменьшать нечего.

0 голосов
/ 13 марта 2019

Используйте параметризованные тесты:

static Stream<String> emailsSource() {
    return Stream.of("test@test.com", "test123@test123.com", "test@test.com.in",
        "test.test2@test.com", "test.test2.test3@test.com", "TEST.2test@test.com");
}

@Test
@MethodSource("emailsSource")
void testCorrectEmailValidator(String email) {
    boolean isValid = UserCredentialsValidator.emailValidator(email);
    assertTrue(isValid);
}

Повторите для usernameSource и т. Д. ИМХО, этого достаточно для устранения дублирования.

Однако, если вы хотите пойти дальше и обобщить его, используйте ссылки на методы,Я не рекомендовал бы это все же.

static Stream<Pair<String,Predicate<String>>> allSources() {
    return Stream.of(
        Pair.of("test@test.com", UserCredentialsValidator::emailValidator),
        Pair.of("username", UserCredentialsValidator::usernameValidationOneArg), // like usernameValidation but with argument userList fixed
        ...
    );
}

@Test
@MethodSource("allSources")
void testAll(Pair<String,Predicate<String>> p) {
    String s = p.getLeft();
    Predicate<String> test = p.getRight();
    boolean isValid = test.apply(email);
    assertTrue(isValid);
}
0 голосов
/ 13 марта 2019

Как я уже говорил в своем комментарии к вашему вопросу, я не уверен, что перестановка вашего кода сильно помогла бы.Однако для сравнения приведу версию Java8 +, в которой используется общий метод:

@Test
void testCorrectEmailValidator() {
  List<String> correctEmails = Arrays.asList("test@test.com", "test123@test123.com", "test@test.com.in",
          "test.test2@test.com", "test.test2.test3@test.com", "TEST.2test@test.com");

  testValidator( "Email", correctEmails , email -> UserCredentialsValidator.emailValidator(email) );
}

@Test
void testCorrectUsernameValidator() {
  List<String> correctUsernames = Arrays.asList("username", "123username", "username3", "user2name",
        "USERNAME", "USERNAME123", "123USERNAME123", "2uSERname33");

  //I don't know where userList does come from but it would need to be final to be used here
  testValidator( "Username", correctUsernames, username -> UserCredentialsValidator.usernameValidation(username, userList) );
}

void testValidator( String name, List<String> data, Predicate<String> validator) {
  for( String element : data ) {
    boolean isValid = validator.test( element );
    System.out.println( name + " is valid:    " + element + "     : " + isValid);
    assertTrue(isValid);
  }
}

В этом конкретном случае оба подхода будут иметь длину 23 строки, тогда как второй может быть проще для повторного использования, но сложнее для понимания и меньшегибкий (например, если вам нужно передать дополнительные параметры и т. д.)

0 голосов
/ 13 марта 2019

То, что вы пытаетесь проверить, указывает на дизайнерский запах .

Самое время для вас изучить шаблон разработки стратегии здесь.

В основном вы основной код будут выглядеть примерно так:

interface IValidator {
     boolean isValid(List<String> yourDataToBeValidated);
}

Теперь создайте несколько классов валидаторов для разных полей, таких как электронная почта, имя пользователя и т. Д.

class EmailValidator implements IValidator {
      boolean isValid(List<String> yourDataToBeValidated){
         //Email specific validations goes here
      }
}

Вы можете создавать больше валидаторов по мере необходимости.

Теперь в вашеммодульные тесты создать new EmailValidator() или new UsernameValidator() и передать emailIds или usernames в метод isValid(), как показано ниже:

    boolean isValid = new EmailValidator().isValid(Arrays.asList("test@test.com", "test123@test123.com");
    assertTrue(isValid);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...