Java NegativeTest 私有方法与反射捕获自定义应用程序异常



所以我正在用模拟的数据库层测试一个AccountService类。 在此 AccountService 类中,有一个私有方法,它根据正则表达式检查从 UI 收到的输入。

我写的阳性测试工作正常:

@Test
public void testEmailPatroonCorrect() throws Exception{
//Correcte emails
List<String> emails = new ArrayList<>();
emails.add("user@domain.com");
emails.add("user@domain.co.in");
emails.add("user.name@domain.com");
emails.add("user_name@domain.com");
emails.add("username@yahoo.corporate.in");
Class<AccountService> foo = AccountService.class;
Method method = foo.getDeclaredMethod("checkEmailPatroon", String.class);
method.setAccessible(true);
assertThatCode(() -> {
for(String email : emails){
method.invoke(AccountService,email);
}}).doesNotThrowAnyException();
}

但是,对于阴性测试(具有错误电子邮件模式的列表(,即使列表中只有一个对象,也为简单起见

@Test
public void testEmailPatroonFout() throws Exception{
//Verkeerde emailpatronen
List<String> emails = new ArrayList<>();
emails.add(".username@yahoo.com");
Class<AccountService> foo = AccountService.class;
Method method = foo.getDeclaredMethod("checkEmailPatroon", String.class);
method.setAccessible(true);
assertThatThrownBy(()->{
for(String email : emails){
method.invoke(AccountService,email);
}
}).isInstanceOf(ApplicationException.class).hasMessage(ApplicationExceptionType.ONGELDIGE_EMAIL.getMsg());
}

测试期间抛出的异常是:java.lang.reflect.InvocationTargetException。在应用程序中,应用程序异常被捕获得很好。 问题是我如何为错误的电子邮件模式列表编写适当的测试?(不使用@VisibleForTesting功能,因为它是一个学校项目(。

非常感谢!

>InvocationTargetException将引发的异常包装在反射式调用的方法中。所以你可能会抓住InvocationTargetException并重新抛出它的原因,但我会把它放到一个实用的方法中,比如

public interface TestMethod<D,A> {
void invoke(D d, A a) throws Throwable;
}
static <D,A> TestMethod<D,A> method(
Class<D> declarer, String name, Class<A> argType) throws ReflectiveOperationException {
Method method = declarer.getDeclaredMethod(name, argType);
method.setAccessible(true);
return (d,a) -> {
try {
method.invoke(d, a);
} catch(InvocationTargetException ex) {
throw ex.getTargetException();
}
};
}

你可以像这样使用

@Test
public void testEmailPatroonFout() throws Exception{
//Verkeerde emailpatronen
List<String> emails = new ArrayList<>();
emails.add(".username@yahoo.com");
TestMethod<AccountService, String> method
= method(AccountService.class, "checkEmailPatroon", String.class);
assertThatThrownBy(() -> {
for(String email : emails){
method.invoke(AccountService, email);
}
}).isInstanceOf(ApplicationException.class)
.hasMessage(ApplicationExceptionType.ONGELDIGE_EMAIL.getMsg());
}

TestMethod接口的形状允许替代实现,例如

static <D,A> TestMethod<D,A> method(
Class<D> declarer, String name, Class<A> argType) throws ReflectiveOperationException {
Method method = declarer.getDeclaredMethod(name, argType);
method.setAccessible(true);
return MethodHandleProxies.asInterfaceInstance(
TestMethod.class, MethodHandles.lookup().unreflect(method));
}

多亏了Holger,我才能为它的目的编写一个工作测试。

@Test
public void testEmailPatroonFoutLoop() throws Throwable {
//Verkeerde emailpatronen
List<String> wrongEmails = new ArrayList<>();
wrongEmails.add(".username@yahoo.com");
wrongEmails.add("username@yahoo.com.");
wrongEmails.add("usernameyahoo.com");
wrongEmails.add("username@yahoo.c");
wrongEmails.add("use..rname@yahoo.com");
Class<AccountService> foo = AccountService.class;
Method method = foo.getDeclaredMethod("checkEmailPatroon", String.class);
method.setAccessible(true);
int countedWrongEmails = 0;
for(String email : wrongEmails){
try{
method.invoke(accServ,email);
}
catch (InvocationTargetException ie){
Exception e = (Exception) ie.getTargetException();
if(e.getMessage().equals(ApplicationExceptionType.ONGELDIGE_EMAIL.getMsg())){
countedWrongEmails++;
}
}
}
assertThat(countedWrongEmails).isEqualTo(wrongEmails.size());
}

虽然我看到了编写 TestMethod 界面的好处和优雅,但我还没有掌握它的复杂性的知识。所以我会坚持这个测试,我将能够在口头考试中解释。

最新更新