Java 延迟EasyMock验证
我正在使用EasyMock为Java中的JUnit测试创建模拟对象。我创建了一个模拟对象,并将其传递给另一个线程,它希望在那里调用方法。在另一个线程中,调用被封装在一个Java 延迟EasyMock验证,java,unit-testing,junit,mocking,easymock,Java,Unit Testing,Junit,Mocking,Easymock,我正在使用EasyMock为Java中的JUnit测试创建模拟对象。我创建了一个模拟对象,并将其传递给另一个线程,它希望在那里调用方法。在另一个线程中,调用被封装在一个try/catch(Throwable)块中,因此当模拟上发生意外调用并因此抛出AssertionError时,该错误被catch块捕获并处理。因此,即使发生了意外调用,测试还是通过了 为了让测试如预期的那样失败,我想延迟所有对EasyMock.verify(mock)调用的验证,这些调用在测试运行程序线程结束时进行。这是可能的吗
try/catch(Throwable)
块中,因此当模拟上发生意外调用并因此抛出AssertionError
时,该错误被catch块捕获并处理。因此,即使发生了意外调用,测试还是通过了
为了让测试如预期的那样失败,我想延迟所有对
EasyMock.verify(mock)
调用的验证,这些调用在测试运行程序线程结束时进行。这是可能的吗?怎么可能?我想正确的解决方案是停止捕捉可丢弃的。这样做会捕获您正在查找的所有错误,这可能非常危险。。。您是否绝对100%确定您需要捕获可丢弃的?为什么?
(如果您确实这样做了,您可以捕获断言错误并重新显示它。但这很难看!)我不确定如何使用EasyMock执行此操作,但这种行为在中是可能的,因为可以在测试结束时指定验证断言。尝试使用漂亮的模拟:
“好笑
在createMock()返回的模拟对象上,所有方法的默认行为都是为所有意外的方法调用抛出AssertionError。如果您想要一个默认允许所有方法调用并返回适当空值(0、null或false)的“好”模拟对象,请改为使用createMock()
对于意外调用,将返回默认值,而不是抛出AssertionError,但是您仍然可以使用verify()方法验证它们(在这种情况下,将抛出AssertionErrors)正如@deterb建议的那样,可以使用Mockito,但您必须知道方法名称,或者必须为每个方法设置期望值。以下是一个例子:
模拟接口:
public interface MyInterface {
void allowedMethod();
void disallowedMethod();
}
捕获断言错误的用户类
:
public class UserClass {
public UserClass() {
}
public static void throwableCatcher(final MyInterface myInterface) {
try {
myInterface.allowedMethod();
myInterface.disallowedMethod();
} catch (final Throwable t) {
System.out.println("Catched throwable: " + t.getMessage());
}
}
}
以及Mockito测试:
@Test
public void testMockito() throws Exception {
final MyInterface myInterface = mock(MyInterface.class);
UserClass.throwableCatcher(myInterface);
verify(myInterface, never()).disallowedMethod(); // fails here
}
EasyMock也可以做到这一点,但需要做一些工作:
@Test
public void testEasyMock() throws Exception {
final AtomicBoolean called = new AtomicBoolean();
final MyInterface myInterface = createMock(MyInterface.class);
myInterface.allowedMethod();
myInterface.disallowedMethod();
final IAnswer<? extends Object> answer = new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
System.out.println("answer");
called.set(true);
throw new AssertionError("should not call");
}
};
expectLastCall().andAnswer(answer).anyTimes();
replay(myInterface);
UserClass.throwableCatcher(myInterface);
verify(myInterface);
assertFalse("called", called.get()); // fails here
}
以及对它的测试:
@Test
public void testEasyMockWithCustomClass() throws Exception {
final MyInterface myInterface = createMock(MyInterface.class);
myInterface.allowedMethod();
final MockedMyInterface mockedMyInterface =
new MockedMyInterface(myInterface);
replay(myInterface);
UserClass.throwableCatcher(mockedMyInterface);
verify(myInterface);
assertFalse("called", mockedMyInterface.isCalled()); // fails here
}
我们捕获了Throwable(丑陋,我同意),因此我们可以拦截(例如)内存不足错误,并进行一些日志记录,然后从此点干净地重新启动应用程序。如果没有其他解决方案,我可能会求助于捕获AssertionError。@Steven-捕获AssertionError并重新引用它几乎肯定比无条件的catch(Throwable t)
block.:-)我也同意deterb的建议:Mockito确实提供了一个更简单的模拟机制(即不必担心nice/strick模拟),并且您只能验证您实际需要的行为。+1:当您当前的库提供您需要的功能时,切换库是不值得的-1:一个好的mock会接受任何方法调用,因此不允许测试是否发生了意外调用(只有在预期调用没有发生的情况下);不过,我试着用它做实验,却找不到更好的解决办法。也许您可以尝试降低测试的粒度,例如测试更具体的方法。
@Test
public void testEasyMockWithCustomClass() throws Exception {
final MyInterface myInterface = createMock(MyInterface.class);
myInterface.allowedMethod();
final MockedMyInterface mockedMyInterface =
new MockedMyInterface(myInterface);
replay(myInterface);
UserClass.throwableCatcher(mockedMyInterface);
verify(myInterface);
assertFalse("called", mockedMyInterface.isCalled()); // fails here
}