简体   繁体   English

Mockito doThrow 在 void 方法上使用 null 参数不抛出异常:我做错了什么?

[英]Mockito doThrow on void method with null argument not throwing exception: What am I doing wrong?

I am unsure if I have found a bug or if I am just doing it wrong.我不确定我是否发现了错误,或者我是否只是做错了。 I am trying to have a mock throw an exception when a method is invoked (relatively easy normally), except the method is of void return type, and the object to be passed in (why the error is thrown) is null .我试图在调用方法时模拟抛出异常(通常相对容易),除了该方法是void返回类型,并且要传入的对象(为什么会抛出错误)为null This can be typed through isNull() to compile, but the error is still not thrown.这个可以通过isNull()输入编译,但是还是不抛出错误。

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();
        }
    }
}

Relevant maven dependencies:相关的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编辑

I added the stripped down real code.我添加了精简的真实代码。 I toyed with the code more this morning, and discovered I was using Mockito's reset() incorrectly.今天早上我更多地玩弄代码,发现我错误地使用了 Mockito 的reset() I thought it would reset the mock to its unverified state, but it also erases the doThrow() stubs.我认为它会将模拟重置为其未验证状态,但它也会删除doThrow()存根。 I had to change the initialization methods as follows:我不得不改变初始化方法如下:

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

As resolved in the comments and edit: Be careful to note that the reset method resets the mock entirely , including both stubs and interactions (the latter for verifications).如评论和编辑中所解决:请注意reset方法完全重置模拟,包括存根和交互(后者用于验证)。

As warned in the Mockito documentation , reset is generally a bad sign in your tests: If it comes in the middle of a test method, generally that method should be split up into multiple smaller tests, and if it comes in an @After or @AfterMethod it means that your test setup is polluting between tests.正如Mockito 文档中警告的那样reset在您的测试中通常是一个不好的迹象:如果它出现在测试方法的中间,通常该方法应该被分成多个较小的测试,如果它出现在@After@AfterMethod这意味着您的测试设置在测试之间存在污染。 Keep your mocks in instance fields, not static fields, initialized in a @Before (JUnit) or @BeforeMethod (TestNG) method to ensure they're fully overwritten before every single test in a test class.将您的@Before保持在实例字段中,而不是静态字段中,在@Before (JUnit) 或@BeforeMethod (TestNG) 方法中初始化,以确保它们在测试类中的每个单独测试之前被完全覆盖。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM