无法模拟服务以使其抛出异常

Posted

技术标签:

【中文标题】无法模拟服务以使其抛出异常【英文标题】:Unable to mock a service to have it throw an exception 【发布时间】:2018-01-13 13:57:38 【问题描述】:

我是使用 Mockito 对 Spring Rest 控制器进行单元测试的新手。这是我的控制器和测试代码。

@RestController
@RequestMapping("/api/food/customer")
public class CustomerController 
    @Autowired
    private CustomerService service;

    @RequestMapping(method=RequestMethod.POST, produces= MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Customer> addCustomer(@RequestBody Customer c)
        Logger log = LoggerFactory.getLogger(CustomerController.class.getName());
        try 
            service.addCustomer(c);
         catch (UserNameException e)
            log.error("UserNameException", e);
            return new ResponseEntity(HttpStatus.BAD_REQUEST);
         catch (Exception e)
            log.error("", e);
            return new ResponseEntity(HttpStatus.BAD_REQUEST);
        
        log.trace("Customer added: " + c.toString());
        return new ResponseEntity(c, HttpStatus.CREATED);
    


@RunWith(MockitoJUnitRunner.class)
@WebMvcTest
public class CustomerRestTest 
    private MockMvc mockMvc;
    @Mock
    private CustomerService customerService;
    @Mock
    private CustomerDao customerDao;
    @InjectMocks
    private CustomerController customerController;

    @Before
    public void setup()
        this.mockMvc = MockMvcBuilders.standaloneSetup(customerController).build();
    

    @Test
    public void testAddDuplicateCustomer() throws Exception 
        Customer myCustomer = mock(Customer.class);
        when(customerService.addCustomer(myCustomer)).thenThrow(UserNameException.class);
        String content = "\"lastName\" : \"Orr\",\"firstName\" : \"Richard\",\"userName\" : \"Ricky\"";
        RequestBuilder requestBuilder = MockMvcRequestBuilders.post("/api/food/customer").accept(MediaType.APPLICATION_JSON).
                content(content).contentType(MediaType.APPLICATION_JSON);
        MvcResult result = mockMvc.perform(requestBuilder).andReturn();
        MockHttpServletResponse response = result.getResponse();
        assertEquals(HttpStatus.BAD_REQUEST.value(), response.getStatus());
    

我正在尝试模拟我的服务层并让它在调用 addCustomer 时抛出我的自定义异常。我要返回 HttpStatus.CREATED 而不是 BAD_REQUEST。对于可能正常工作的服务模拟行(带有 thenThrow 的行),我可以做些什么不同的事情?

【问题讨论】:

【参考方案1】:

我认为这是因为您希望在您的when 子句中有一个特定的客户实例,但这永远不会发生。 Spring 将反序列化您的 JSON,并为您的方法设置另一个客户实例。

尝试改变这个:

when(customerService.addCustomer(myCustomer)).thenThrow(UserNameException.class);

到这里:

when(customerService.addCustomer(any())).thenThrow(UserNameException.class);

【讨论】:

做到了!谢谢 dzatorsky。

以上是关于无法模拟服务以使其抛出异常的主要内容,如果未能解决你的问题,请参考以下文章

JLS 的哪些部分证明能够像未经检查一样抛出已检查异常?

使用 NSubstitute 模拟出现问题时抛出异常的方法

让 EasyMock 模拟对象抛出异常

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

源码分析-AutoCloseable

Spark记录-Scala异常处理与文件I/O