我的Spring Boot应用程序中包含以下代码,该代码可验证电子邮件地址
class EmailValidation {
public static void validate(List<String> s){
try {
for (String address : s) {
if (s == null || s.indexOf("@") < 0) {
throw new InvalidEmailAddressException("Email address is invalid ");
}
new InternetAddress(s);
}
} catch(AddressException e){
LOGGER.Error("Please validate email addresses");
}
catch(InvalidEmailAddressesException e){
LOGGER.error(e.getMessage());
}
}
class InvalidEmailAddressException extends Exception {
public InvalidEmailAddressException(String message) {
super(message)
}
}
}
我想编写一个Junit测试,该测试将验证是否抛出InvalidEmailAddressesException并执行了CAUGHT。如何在JUnit中做到这一点?
答案 0 :(得分:0)
总的来说,我同意这种测试可能是不必要的评论。
但是,如果我想测试类似的东西,我将分别测试这两种情况,这需要对您的代码进行少量修改。
首先,我将构建一个仅在存在异常时抛出异常的方法。
public static void checkAddresses(List<String> s) throws AddressException, InvalidEmailAddressException {
for (String address : s) {
if (s == null || s.indexOf("@") < 0) {
throw new InvalidEmailAddressException("Email address is invalid ");
}
new InternetAddress(s);
}
}
然后我会像这样在您的代码中使用它:
class EmailValidation {
public static void validate(List<String> s){
try {
checkAddresses(s); // a wrapper method that throws the expected exceptions
} catch(AddressException e){
LOGGER.Error("Please validate email addresses");
}
catch(InvalidEmailAddressesException e){
LOGGER.error(e.getMessage());
}
}
// add checkAddresses here or somewhere appropriately
class InvalidEmailAddressException extends Exception {
public InvalidEmailAddressException(String message) {
super(message)
}
}
}
然后,我将为checkAddresses
编写单独的测试,以测试是否为expected,并且为validate
编写单独的测试(可能使用与输入相同的输入) checkAddresses
),如果未引发异常,则应该通过。
此外,如果您想验证自己的日志,可以尝试使用that之类的东西。
答案 1 :(得分:0)
实际上将Java Exception用于常见原因被认为是一种不好的做法,正如@Michael所说,异常必须是特殊的,因为
但是,创建用于包装验证数据的自定义对象是一件好事,InvalidEmailAddressException
可以变成CheckedEmail
:
import java.util.List;
import java.util.stream.Collectors;
public class EmailValidator {
public List<CheckedEmail> validate(List<String> emailAddresses) {
return emailAddresses.stream().map(this::validate).collect(Collectors.toList());
}
public CheckedEmail validate(String emailAddress) {
String[] emailParts = emailAddress.toString().split( "@", 3 );
final boolean valid;
if ( emailParts.length != 2 ) {
valid = false;
} else {
// More validation can go here using one or more regex
valid = true;
}
return new CheckedEmail(emailAddress, valid);
}
public static final class CheckedEmail {
private final String emailAddress;
private final boolean valid;
private CheckedEmail(String emailAddress, boolean valid) {
this.emailAddress = emailAddress;
this.valid = valid;
}
public String getEmailAddress() {
return emailAddress;
}
public boolean isValid() {
return valid;
}
}
}
这反过来可以很容易地进行测试(并通过参数化测试进行了改进):
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
public class EmailValidatorTest {
private final EmailValidator emailValidator = new EmailValidator();
@Test
public void invalid_email() {
EmailValidator.CheckedEmail checkedEmail = emailValidator.validate("missing.an.at.symbol");
assertThat(checkedEmail.isValid()).isFalse();
}
@Test
public void valid_email() {
EmailValidator.CheckedEmail checkedEmail = emailValidator.validate("at.symbol@present");
assertThat(checkedEmail.isValid()).isTrue();
}
@Test
public void multiple_email_addresses() {
List<String> emailAddresses = Arrays.asList("missing.an.at.symbol", "at.symbol@present");
List<EmailValidator.CheckedEmail> checkedEmails = emailValidator.validate(emailAddresses);
assertThat(checkedEmails)
.extracting(ce -> ce.getEmailAddress() + " " + ce.isValid())
.containsExactly(
"missing.an.at.symbol false",
"at.symbol@present true");
}
}
如果某个地方只是记录下来,那么:
List<EmailValidator.CheckedEmail> checkedEmails = emailValidator.validate(emailAddresses);
checkedEmails.stream()
.filter(ce -> !ce.isValid())
.map(ce -> String.format("Email address [%s] is invalid", ce.getEmailAddress()))
.forEach(logger::error);
希望这会有所帮助!
答案 2 :(得分:0)
不要以这种方式进行测试。您应该仅测试代码的指定行为,而不是其实现详细信息。
如果您正在测试的方法将委托给抛出 checked 异常的方法,并且您正在测试的方法也没有throws
声明检查异常的 compiler 将强制该方法捕获异常。因此,在这种情况下,不需要进行单元测试。
如果您要测试的方法委托抛出 unchecked 异常的方法,请查阅该方法的规范以确定被测方法是否也抛出(传播)该异常。例外。如果它不能传播异常,则应创建一个测试用例,以使委托的方法引发该未经检查的异常。如果该方法传播异常,则测试用例将失败。怎么做?这取决于委托给的方法,但是在大多数情况下,您将需要使用“依赖注入”来提供引发异常的模拟对象。