[英]How to write a junit to verify if an exception thrown by the method is caught?
我的春季啟動應用程序中包含以下代碼,該代碼可驗證電子郵件地址
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中做到這一點?
總的來說,我同意這樣的評論,即這種測試可能是不必要的。
但是,如果我想測試類似的東西,我將分別測試這兩種情況,這需要對您的代碼進行少量修改。
首先,我將構造一個僅在存在異常時拋出異常的方法。
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
編寫單獨的測試,以測試是否預期發生異常,以及為validate
編寫單獨的測試(可能具有與checkAddresses
相同的輸入),如果未引發異常,則該測試應通過。
另外,如果您想驗證你的日志可能是你可以嘗試像那個 。
實際上,將java Exception用於常見原因被認為是一種不好的做法,正如@Michael所說, Exceptions必須是例外 ,因為
然而,對於包裝驗證數據創建一個自定義對象是一件好事, 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);
希望這可以幫助 !
不要以這種方式進行測試。 您應該僅測試代碼的指定行為,而不是其實現詳細信息。
如果您正在測試的方法委托給引發已檢查異常的方法,並且您正在測試的方法未同時聲明其throws
已檢查異常,則編譯器將強制該方法捕獲該異常。 因此,在這種情況下,不需要進行單元測試。
如果您正在測試的方法委托引發未檢查異常的方法,請查閱該方法的規范,以確定被測方法也拋出(傳播)該異常是否可以接受。 如果它不能傳播異常,則應創建一個測試用例,以使委托的方法引發該未經檢查的異常。 如果該方法傳播異常,則測試用例將失敗。 怎么做? 這取決於委托給的方法,但是在大多數情況下,您將需要使用“依賴注入”來提供引發異常的模擬對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.