我想测试委托给服务方法“isInProgress”的JSF Backing-Bean方法“isInProgress”。当服务方法抛出异常时,bean应该在特定事件记录器上放置一个事件并返回false。
当我调试以下测试时,我进入了catch块。模拟服务不会抛出异常,但会返回“默认答案”,对于布尔值,它是false。 我做错了什么?
我也想知道是否可以以某种方式避免围绕“when”调用的try-catch,因为被测试的bean吞下了实际的异常。事实上,我认为“声明性地”将方法的名称传递给“when”就足够了。 有没有办法让它更清洁?
@Test
public void testIsInProgressExeption() {
//prepare object and inputs
MyBean bean = new MyBean();
MyService service = mock(MyAdapterService.class);
bean.setService(service);
try {
when(bean.getService().isInProgress()).thenThrow(new Exception());
} catch (Exception e) {
//prepare expected object and result
MyBean expectedBean = new MyBean();
expectedBean.setService(service);
boolean expected = false;
//execute method under test
boolean actual = bean.isInProgress();
//check return values and exceptions
assertEquals(expected, actual);
//check that bean did not change unexpectedly
assertTrue(bean.equals(expectedBean));
//check sideeffects on event log
assertTrue(logEvents.containsMessage("MDI09"));
}
}
此处参考更新的测试:
@Test
public void testIsInProgressExeption() throws Exception {
//prepare object and inputs
MyBean bean = new MyBean();
MyService service = mock(MyAdapterService.class);
bean.setService(service);
when(bean.getService().isInProgress()).thenThrow(new Exception());
//prepare expected object and result
MyBean expectedBean = new MyBean();
expectedBean.setService(service);
boolean expected = false;
//execute method under test
boolean actual = bean.isInProgress();
//check return values and exceptions
assertEquals(expected, actual);
//check that bean did not change unexpectedly
assertTrue(bean.equals(expectedBean));
//check sideeffects on event log
assertTrue(logEvents.containsMessage("MDI09"));
}
答案 0 :(得分:3)
将when子句移出try块并将其更改为:
when(service.isInProgress()).thenThrow(new Exception());
现在它应该在调用时抛出异常。
答案 1 :(得分:0)
对于记录,我正在进行状态测试。有趣的是,Fowler在http://martinfowler.com/articles/mocksArentStubs.html中发布了一篇非常好的文章,该文章的路线完全相同,但后来将其与基于模拟和交互的测试区分开来。
答案 2 :(得分:-1)
你做错了。首先,您应该使用BDD BDD 或 AAA 关键字进行测试:
@Test public void testIsInProgressExeption() {
// given
// when
// then
}
在 给出 部分,您将编写灯具,即测试场景的设置。在 部分,您将调用生产代码,即测试主题。最后,在 部分,您将编写验证和/或断言。
存根进入固定装置,因此这条线错位,它不属于这里,它只是行为的定义。
when(bean.getService().isInProgress()).thenThrow(new Exception());
但是,您应该直接使用服务引用而不是bean.getService()
,这是很难的。
我真的不明白你为什么要在catch子句中创建bean的新实例,这很奇怪。但这是我写下测试的方式。请注意我在单元测试名称中解释测试的实际测试行为,在camel情况下写这个是读取痛苦的方法,所以我使用强调约定,它没关系在测试中。
@Test public void when_service_throw_Exception_InProgress_then_returns_false() throws Exception {
// given
MyBean bean = new MyBean();
MyService service = mock(MyAdapterService.class);
bean.setService(service);
when(service.isInProgress()).thenThrow(new Exception());
// when
boolean result = bean.isInProgress();
// then
assertFalse(result);
}
此外,我会在事件上拆分断言,这是一种不同的行为:
@Test public void when_service_throw_Exception_InProgress_then_log_event_MDI09() throws Exception {
// given
MyBean bean = new MyBean();
MyService service = mock(MyAdapterService.class);
bean.setService(service);
// somehow set up the logEvents collaborator
when(service.isInProgress()).thenThrow(new Exception());
// when
bean.isInProgress();
// then
assertTrue(logEvents.containsMessage("MDI09"));
}
你甚至可以进一步简化夹具,如果你使用JUnit,你可以编写这段代码:
@RunWith(MockitoJUnitRunner.class)
public class MyBeanTest {
@Mock MyService service;
@Mock LogEvents logEvents;
@InjectMocks MyBean bean;
@Test public void when_service_throw_Exception_InProgress_then_log_event_MDI09() throws Exception {
// given
when(service.isInProgress()).thenThrow(Exception.class);
// when
bean.isInProgress();
// then
verify(logEvents).logEvent("MDI09");
}
}
在上面的示例中,我还推断了日志事件的内容,但这只是为了说明可能的事情。