2015-06-10 2 views
2

Я не уверен, нашел ли я ошибку или если я просто делаю это неправильно. Я пытаюсь получить ложный выброс исключения при вызове метода (относительно легко нормально), за исключением того, что метод имеет тип возвращаемого типа void, а объект, который должен быть передан (почему ошибка выбрасывается), равен null. Это можно ввести в isNull() для компиляции, но ошибка все равно не выбрасывается.Mockito doThrow on void method с аргументом null, исключающим исключение: что я делаю неправильно?

package some.example; 

import static org.mockito.Matchers.isNull; 
import static org.mockito.Mockito.doThrow; 
import static org.mockito.Mockito.reset; 
import static org.mockito.Mockito.verify; 
import static org.mockito.MockitoAnnotations.initMocks; 

import javax.jms.Message; 
import javax.jms.MessageListener; 

import org.mockito.Mock; 
import org.springframework.jms.listener.AbstractMessageListenerContainer; 
import org.springframework.jms.listener.SessionAwareMessageListener; 
import org.testng.annotations.AfterMethod; 
import org.testng.annotations.BeforeClass; 
import org.testng.annotations.Test; 

public class TestClass { 
    @Mock 
    private AbstractMessageListenerContainer messageContainer; 

    @BeforeClass 
    public void setUpMocks() { 
     initMocks(this); 

     doThrow(new IllegalArgumentException()).when(messageContainer).setupMessageListener(
       isNull(MessageListener.class)); 
     doThrow(new IllegalArgumentException()).when(messageContainer).setupMessageListener(
       isNull(SessionAwareMessageListener.class)); 
    } 

    @AfterMethod 
    public void resetMocks() { 
     reset(messageContainer); 
    } 

    @Test(expectedExceptions = { IllegalArgumentException.class }) 
    public void testSetUpQueueConsumerWithNullMessageListener() throws Exception { 
     final MessageListener messageListener = null; 
     try (final QueueConsumer consumer = new QueueConsumer(messageContainer, messageListener)) { 
     } finally { 
      verify(messageContainer).setupMessageListener(messageListener); 
     } 
    } 

    @Test(expectedExceptions = { IllegalArgumentException.class }) 
    public void testSetUpQueueConsumerWithNullSessionAwareMessageListener() throws Exception { 
     final SessionAwareMessageListener<Message> messageListener = null; 
     try (final QueueConsumer consumer = new QueueConsumer(messageContainer, messageListener)) { 
     } finally { 
      verify(messageContainer).setupMessageListener(messageListener); 
     } 
    } 

    public class QueueConsumer implements AutoCloseable { 
     private final AbstractMessageListenerContainer messageContainer; 

     QueueConsumer(final AbstractMessageListenerContainer messageContainer, 
       final SessionAwareMessageListener<? extends Message> messageListener) { 
      this(messageContainer); 
      this.messageContainer.setupMessageListener(messageListener); 
     } 

     QueueConsumer(final AbstractMessageListenerContainer messageContainer, final MessageListener messageListener) { 
      this(messageContainer); 
      this.messageContainer.setupMessageListener(messageListener); 
     } 

     private QueueConsumer(final AbstractMessageListenerContainer messageContainer) { 
      if (messageContainer == null) { 
       throw new IllegalArgumentException("MessageListenerContainer cannot be null"); 
      } 
      this.messageContainer = messageContainer; 
     } 

     public void stop() { 
      messageContainer.stop(); 
     } 

     @Override 
     public void close() throws Exception { 
      stop(); 
     } 
    } 
} 

Соответствующие зависимости Maven:

<dependency> 
    <groupId>org.testng</groupId> 
    <artifactId>testng</artifactId> 
    <version>6.8.21</version> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>org.mockito</groupId> 
    <artifactId>mockito-core</artifactId> 
    <version>2.0.8-beta</version> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-jms</artifactId> 
    <version>${org.springframework.version}</version> 
</dependency> 

EDIT

Я добавил усеченную реальный код. Сегодня утром я играл с кодом больше, и обнаружил, что неправильно использовал Mockito's reset(). Я думал, что он сбросит фальшивку на свое непроверенное состояние, но также удалит doThrow() заглушки. Я должен был изменить методы инициализации следующим образом:

@BeforeClass 
public void setUpMocks() { 
    initMocks(this); 
} 

@BeforeMethod 
public void setUpThrows() { 
    doThrow(new IllegalArgumentException()).when(messageContainer).setupMessageListener(
      isNull(MessageListener.class)); 
    doThrow(new IllegalArgumentException()).when(messageContainer).setupMessageListener(
      isNull(SessionAwareMessageListener.class)); 
} 
+0

Не уверен, что я не тестировал ваш код, но похоже, что «interfaceMock» не является нулевым, поскольку он аннотируется с помощью @Mock, поэтому ваш метод doSomething НЕ вызывается с нулевым аргументом. – Joel

+0

Вы должны знать, что аннотация @Mock инициализирует макет, полученный из вашего класса. – Joel

+0

Убедитесь, что ваш метод 'initMocks' аннотирован' @ Before', а не '@ BeforeClass'. Кроме того, здесь есть класс SimpleExample, и есть ли у него какие-либо окончательные методы? –

ответ

1

В соответствии с решением в комментариях и редактирования: Будьте осторожны, чтобы отметить, что метод reset сбрасывает издеваться полностью, включая как окурки и взаимодействий (последний для проверки).

Как warned in the Mockito documentation, reset, как правило, плохой знак в тестах: Если он приходит в середине метода испытания, как правило, этот метод должен быть разделен на несколько небольших тестов, и если он приходит в @After или @AfterMethod его по означает, что ваша тестовая установка загрязняет между тестами. Держите свои mocks в полях экземпляра, а не в статических полях, инициализированном методом @Before (JUnit) или @BeforeMethod (TestNG), чтобы обеспечить их полную перезапись перед каждым тестом в тестовом классе.

+0

Хорошая точка. Я понял, как только выяснил проблему и переписал пару тестов, чтобы использовать методы локальных макетов. – FinalDoom

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