简体   繁体   English

Mockito doThrow() 方法使我的测试因给定异常而失败

[英]Mockito doThrow() method makes my test fail with the given exception

I'm testing the error case for when my injected StatefulBeanToCsv dependency throws an exception.我正在测试注入的StatefulBeanToCsv依赖项引发异常的错误情况。 However, Mockito's doThrow() method is just making my test fail, rather than allowing that exception to be verified using assertThrows() .但是,Mockito 的doThrow()方法只是让我的测试失败,而不是允许使用assertThrows()验证该异常。

I'm injecting my StatefulBeanToCsv dependency through a BeanFactory rather than constructor/setter injection, because I need to pass it a Writer as an argument.我通过BeanFactory而不是构造函数/设置器注入注入我的StatefulBeanToCsv依赖项,因为我需要将Writer作为参数传递给它。

The test is below, and fails at the asterisk.测试如下,星号处失败。 The CSV bean works okay in my success tests - the main difference I can think of in this case is the use of the do / when Mockito pattern rather than the when / then one used elsewhere (which doesn't allow exceptions to be thrown from void methods): CSV bean 在我的成功测试中工作正常 - 在这种情况下我能想到的主要区别是使用do / when Mockito 模式而不是when / then在其他地方使用的模式(它不允许从无效方法):

@Test
    void willThrowSwaggerListToCsvExceptionIfCsvWriterThrowsCsvException() throws CsvFieldAssignmentException {
        // given
        List<ApiSummary.Endpoint> endpointList = getEndpointList(6);
        doReturn(endpointBeanToCsvMock)
                .when(beanFactoryMock).getBean(eq(StatefulBeanToCsv.class), eq(ApiSummary.Endpoint.class), any(Writer.class), any(String[].class));
        doThrow(CsvFieldAssignmentException.class)
*               .when(endpointBeanToCsvMock).write(endpointList);
        // when, then
        assertThrows(SwaggerToCsvException.class, () -> underTest.listToResource(endpointList, ApiSummary.Endpoint.class));
    }

The method I'm testing is below (and I'm expecting the void "write" method at the asterisk to throw the exception).我正在测试的方法如下(我希望星号处的 void “write” 方法抛出异常)。

public <T> ByteArrayResource listToResource(List<T> beanList, Class<T> clazz, String... columnOrder) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try (Writer writer = new OutputStreamWriter(out)) {
            StatefulBeanToCsv<T> beanToCsv = beanFactory.getBean(StatefulBeanToCsv.class, clazz, writer, columnOrder);
*           beanToCsv.write(beanList);
        } catch (CsvFieldAssignmentException | IOException e) {
            throw new SwaggerToCsvException("Error converting List of type " + clazz.getSimpleName() + " to csv", e);
        }
        byte[] bytes = out.toByteArray();
        return new ByteArrayResource(bytes);
    }

Am I missing something?我错过了什么吗?

Edit - stack trace:编辑 - 堆栈跟踪:

java.lang.InstantiationError: com.opencsv.exceptions.CsvFieldAssignmentException

    at jdk.internal.reflect.GeneratedSerializationConstructorAccessor3.newInstance(Unknown Source)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
    at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
    at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:73)
    at org.mockito.internal.creation.instance.ObjenesisInstantiator.newInstance(ObjenesisInstantiator.java:21)
    at org.mockito.internal.stubbing.answers.ThrowsExceptionForClassType.getThrowable(ThrowsExceptionForClassType.java:23)
    at org.mockito.internal.stubbing.answers.AbstractThrowsException.validateFor(AbstractThrowsException.java:43)
    at org.mockito.internal.stubbing.InvocationContainerImpl.addAnswer(InvocationContainerImpl.java:72)
    at org.mockito.internal.stubbing.InvocationContainerImpl.setMethodForStubbing(InvocationContainerImpl.java:128)
    at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:53)
    at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
    at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:33)
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:56)
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor$DispatcherDefaultingToRealMethod.interceptSuperCallable(MockMethodInterceptor.java:141)
    at com.opencsv.bean.StatefulBeanToCsv$MockitoMock$321003460.write(Unknown Source)
    at com.foo.myproject.csv.CsvFactoryTest.willThrowSwaggerListToCsvExceptionIfCsvWriterThrowsCsvException(CsvFactoryTest.java:96)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)

As M.Deinum mentions in a comment, the error here isn't that the exception is being thrown, but rather that Mockito is failing to instantiate the exception, in order to throw it for you.正如 M.Deinum 在评论中提到的那样,这里的错误不是抛出异常,而是 Mockito 未能实例化异常,以便为您抛出异常。

Note that the example in the Mockito documentation shows the exception being instantiated - that is, the doThrow() method is taking an instance of the exception, not the class of the exception that you want to throw:请注意, Mockito 文档中的示例显示了正在实例化的异常 - 也就是说, doThrow()方法正在获取异常的实例,而不是您要抛出的异常的 class:

doThrow(new RuntimeException()).when(mockedList).clear();

The Javadoc does also show that you can provide a class, as you have, and says that it will be instantiated, but doesn't give details on what constructors are required. Javadoc也确实表明您可以提供 class,就像您一样,并说它将被实例化,但没有详细说明需要哪些构造函数。 Without trying it myself, I would guess that will only work for exceptions with a default (no-args) constructor.如果不亲自尝试,我猜这仅适用于具有默认(无参数)构造函数的异常。

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

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