Mockito 抛出异常

Posted

技术标签:

【中文标题】Mockito 抛出异常【英文标题】:Mockito throw Exception 【发布时间】:2014-04-06 00:32:32 【问题描述】:
@Test(expectedExceptions=DataAccessException.class)
public void testUpdateSubModuleOrderDateExceptionCheck() 
    //some code to initialize//
    UserSubModuleDao userSubModuleDao = mock(UserSubModuleDao.class);
    userModuleServiceImpl.setUserSubModuleDao(userSubModuleDao);
    UserSubModule userSubModule=new UserSubModule();
    UserSubModuleId userSubModuleId=new UserSubModuleId();
      when(userSubModuleDao.findById(any(UserSubModuleId.class),eq(false))).thenThrow(DataAccessException.class);

    userModuleServiceImpl.updateSubModuleOrder(data, moduleSysId, userId);

我想为代码覆盖抛出 Db 异常。如果我给出预期的异常为:Exception.class 但不适用于DataAccessException.class

我在原班的方法如下:

public void updateSubModuleOrder(Long[] data, Long moduleSysId, Long userId) 
    try 

        for (int i = 0; i < data.length; i++) 
            SubModule subModule=new SubModule();
            subModule.setSubModuleId(data[i]);
            UserSubModuleId userSubModuleId = new UserSubModuleId();
            userSubModuleId.setSubModuleId(subModule);
            userSubModuleId.setUserId(userId);
            userSubModuleId.setUserModuleId(moduleSysId);
            UserSubModule userSubmodule = new UserSubModule();
            userSubmodule = userSubModuleDao.findById(userSubModuleId,
                    false);
catch (DataAccessException ewmsDataExp) 
        LOGGER.error(
                "Database Exception while updateSubModuleOrder because of ",
                ewmsDataExp.getMessage());
        throw new EWMSServiceException(
                "Database Exception while updateSubModuleOrder"
                        + ewmsDataExp.getMessage());
     catch (Exception exp) 
        LOGGER.error(
                "System Exception while updateSubModuleOrder because of ",
                exp.getMessage());
        throw new EWMSServiceException(
                "Database Exception while updateSubModuleOrder"
                        + exp.getMessage());
    *

我得到了错误

FAILED: testUpdateSubModuleOrderDateExceptionCheck
org.testng.TestException: 
**Expected exception org.springframework.dao.DataAccessException but got    org.testng.TestException:** 
**Expected exception org.springframework.dao.DataAccessException but got         java.lang.InstantiationError: org.springframework.dao.DataAccessException**
    at org.testng.internal.Invoker.handleInvocationResults(Invoker.java:1497)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1245)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)

还有一些错误行。...

Default test

测试运行:1,失败:1,跳过:0

================================================

================================================

【问题讨论】:

当您的班级明确捕获 DataAccessException 并将其转换为其他内容时,您为什么期待 DataAccessException 【参考方案1】:

改变这个:

thenThrow(DataAccessException.class)

thenThrow(new DataAccessException("...") )

例子:

when(userSubModuleDao.findById(any(UserSubModuleId.class),eq(false))).thenThrow(new DataAccessException("..."));

只有当 Exception 类型具有 No-Arg 构造函数且 Spring 异常没有构造函数时,您才能传递 Class 引用。

【讨论】:

它说 DataAccessException 不能被实例化 是的,它说这个类不能被实例化,因为它试图使用一个无参数的构造函数来实现它。而且这个类没有这样的构造函数。 DataAccessException 是一个抽象类,所以你不能实例化它。你可以改用new DataRetrievalFailureException("reason") 它仍然报错..."java.lang.AssertionError: Expected exception: org.springframework.dao.DataAccessException"...即使我用过'new DataAccessException("..." )' 为我工作,+1,但那个 在做什么?【参考方案2】:

试试

Mockito.doThrow(new Exception()).when(mockedObject).methodName(...);

【讨论】:

这是一个更正确的答案,因为 when...thenThrow 不适用于返回 void 的方法。 @SaurabhPatil - 你将如何解决 void 方法抛出异常的问题? @PAA 你的意思是说你想让 void 方法在测试期间抛出异常吗?是的,这正是这个答案比另一个更好的原因。【参考方案3】:

正如 Jen S 所说:

只有当 Exception 类型具有 No-Arg 构造函数且 Spring 异常没有构造函数时,您才能传递 Class 引用。

我的解决方案是使用 Mockito:

Mockito.when(mockedObject.method(Mockito.anyString())).thenThrow(Mockito.mock(DataAccessException.class));

【讨论】:

以上是关于Mockito 抛出异常的主要内容,如果未能解决你的问题,请参考以下文章

Mockito 如何模拟和断言抛出的异常?

使用 Mockito 从模拟中抛出已检查的异常

Mockito:参数的模拟服务抛出空指针异常

称为验证的 Mockito Kotlin 单元测试方法抛出空指针异常

模拟接口没声明异常抛出异常

如何验证没有抛出异常