2012-02-23 4 views
2

Я хочу проверить метод JSF Backing-Bean «isInProgress», который делегирует сервис-метод «isInProgress». Когда метод службы генерирует исключение, компонент должен помещать событие в конкретный регистратор событий и возвращать значение false.Отказывание службы, которая выдает исключение?

Когда я отлаживаю следующий тест, я попадаю в блок catch. Обманутая служба не генерирует исключение, а возвращает «ответ по умолчанию», который является ложным для булевского. Что я делаю неправильно?

Я также задаюсь вопросом, можно ли каким-либо образом избежать попыток уловить вокруг вызова «когда», поскольку фактическое исключение проглатывается тестируемым компонентом. На самом деле я думаю, что «декларативно» передать имя метода «когда» должно быть достаточно. Есть ли способ получить этот уборщик?

@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")); 

} 

ответ

2

Перемещение когда пункт из блока попытаться изменить его на:

when(service.isInProgress()).thenThrow(new Exception()); 

Теперь он должен бросить исключение при вызове.

+0

, но service.isInProgress() выбрасывает исключение, поэтому компилятор заставляет меня справляться с этим! – Bastl

+0

Ах, добавление бросков в test-decl делает. – Bastl

+1

Добавить исключение в подписи методов тестирования –

-1

Вы делаете это неправильно. Во-первых, вы должны выложить свой тест с BDD или AAA ключевых слов, с BDD:

@Test public void testIsInProgressExeption() { 
    // given 

    // when 

    // then 

} 

В данного часть вы будете писать ваше приспособление, то есть настройки вашего тестового сценария. В , когда часть вы назовете производственным кодом, то есть испытанным объектом. Наконец, в , когда часть вы напишете ваши подтверждения и/или утверждения.

Заглушки входят в приспособление, поэтому эта линия неуместна, она здесь не принадлежит, это просто определение поведения.

when(bean.getService().isInProgress()).thenThrow(new Exception()); 

Однако следует непосредственно справочная служба вместо bean.getService(), это akward.

Я действительно не понимаю, почему вы создаете новый экземпляр компонента в предложении catch, это странно. Но вот как я написал тест. Обратите внимание на то, как я объясняю в модульном тесте название, какое поведение тестирует на тестирование, написав это в случае с верблюдом. Это полезно для чтения, поэтому я использую ., это нормально в тестах.

@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"); 
    } 
} 

В приведенном выше примере я также экстраполирован на материал журнала событий, но это просто, чтобы дать представление о том, что возможно.

+1

Я не очень разбираюсь в тестировании фреймворков, но, как вы видите в комментариях, мой подход очень систематичен, и на самом деле я не знаю лучшего подхода (и он использует простые средства!). Я тестирую не только входные образцы с возвращаемыми значениями. Я также проверяю изменения состояния тестируемого объекта (что не должно происходить в этом случае) и возможные побочные эффекты в других объектах. Кроме того, ваш тон довольно агрессивен. – Bastl

+0

Прошу прощения, если тон казался суровым или агрессивным, это было не мое намерение. В любом случае основная идея заключалась в том, чтобы дать прогрессивный способ проведения специальных и фокализованных тестов, делая это, чтобы потенциально привести свой код в лучший дизайн. Простой факт комментирования того, что делает в тесте, - это ** запах **. Кроме того, реальные намерения вашего теста не выражаются в 'testIsInProgressException', то есть при тестировании в вашем компоненте нет эффекта со стороны государства, поэтому стоит написать тест для этого. – Brice

+0

Практика TDD может помочь в этом вопросе. Вот отличная книга, в которой много ценной информации [Растущее объектно-ориентированное программное обеспечение, управляемое тестированием] (http://www.growing-object-oriented-software.com). Этот блог из Джеймса Карра перечислил [test anti-patterns] (http://blog.james-carr.org/2006/11/03/tdd-anti-patterns/). Конечно, есть много других интересных чтений. – Brice

0

Для записей я проводил государственное тестирование. Интересно, что Фаулер опубликовал в http://martinfowler.com/articles/mocksArentStubs.html очень хорошую статью, которая идет совсем по тому же пути, но затем отличает ее от насмешек и тестирования на основе взаимодействия.

Смежные вопросы