你好,我正在测试具有一些验证方法的类,我一直在想是否有一种减少重复的代码的方法。
@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);
}
}
我还为其他字段(例如用户名等)都有验证器。我正在考虑实现一个可以接受的帮助方法:测试凭据为字符串,列表,但我对最后一个参数有问题 - 验证方法,不确定如何通过。
我想用某种方法替换的代码是for循环。
我恐怕您的测试质量低。
应立即解决的问题包括
-
UserCredentialsValidator.usernameValidation(username, userList);
该方法不应采用第二个参数。从API消费者中隐藏了从该清单中取回该列表的地方。 -
List<String> correctEmails = Arrays.asList(...)
和List<String> correctUsernames = Arrays.asList(...)
应删除。您最好用@ParameterizedTest
和@ValueSource
参数化测试。 -
我宁愿删除
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);
}
现在没有什么可减少的。
正如我在对您的问题的评论中所说的那样,我不确定对您的代码重新安排会有很大帮助。但是,作为比较,这是使用常见方法的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行,而第二行可能更容易重复使用,但很难理解且灵活较低(例如,如果您需要传递其他参数等)
使用参数化测试:
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);
}
重复用户室内的等等。恕我直言,这足以消除重复。
但是,如果您想进一步进行概括,请使用方法参考。我不推荐。
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);
}
您正在努力测试的事实表明设计气味。
是您在这里探索策略设计模式的好时机。
基本上您主代码看起来像
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);