Mockito for unit testing

background

How do you say the importance of unit testing? According to the process specification, unit tests should be run every time before going online to confirm that the pass rate is 100%. Otherwise, after we have modified the existing code, if we only rely on the regression verification of the test classmates, it is easy to miss scenes, or implicitly undiscovered problems, and when we modify the public parts, the amount of regressions may be very large. . However, the reality is generally that business codes cannot be written, and there is no time to write single tests, let alone quality single tests.

Our current project single test requirement is that the line coverage rate is above 60% and the pass rate is 100%. Many times, for this indicator, the order will be supplemented afterwards, but in fact, this is of little significance. Unit testing should be completed when developing business code, and single testing should be used to verify the correctness of the code business logic. Unit tests and code comments should always be consistent with the code.

practice

Class injection

@MockBean: 类的所有方法都需要mock时,使用该注解
@SpyBean: 类的部分方法需要mock时,使用该注解

Mock use

package com.yst.b2b.dms.controller.dealer.xls;

import com.alibaba.fastjson.JSON;
import com.yst.b2b.dms.TestApplication;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.WebApplicationContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * MockTest
 *
 * @author xyang010
 * @date 2020/8/23
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@Transactional
public class MockTest {

    @Autowired
    private WebApplicationContext webApplicationContext;
    protected MockMvc mockMvc;
    @Mock
    protected HttpServletResponse response;
    @Mock
    protected HttpServletRequest request;

    @Before
    public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

    @MockBean
    private UserService userService;
    @SpyBean
    private OrderService orderService;

    /**
     * mock service方法的controller接口单测
     * @throws Exception
     */
    @Test
    public void getUserInfo() throws Exception {
        Mockito.doReturn(new UserInfo()).when(userService).getUserInfo(Matchers.any());
        MvcResult mvcResult = mockMvc
                .perform(MockMvcRequestBuilders
                        .post("/getUserInfo")
                        .param("userName", Matchers.any())
                        .accept(MediaType.APPLICATION_JSON_UTF8)
                        .contentType(MediaType.APPLICATION_JSON_UTF8)
                )
                .andDo(MockMvcResultHandlers.print())
                .andReturn();
        MyResult<UserInfo> result = JSON.parseObject(mvcResult.getResponse().getContentAsString(), new TypeReference<MyResult<UserInfo>>() {});
        Assert.assertTrue(result.isSuccess());
    }

    /**
     * 直接测试service的方法
     */
    @Test
    public void getOrderInfo() {
        OrderInfo orderInfo = orderService.getOrderInfo(1L);
        Assert.assertNotNull(orderInfo);
    }

    /**
     * 测试service方法, mock该方法内调用的同一service内的其他方法
     */
    @Test
    public void getOrderInfoMock() {
        Mockito.doNothing().when(orderService).checkParam(Matchers.any());
        Mockito.doNothing().when(orderService).checkOrderExist(Matchers.any());
        orderService.getOrderInfo(1L);
    }

    /**
     * 测试异常场景
     */
    @Test(expected = RuntimeException.class)
    public void getOrderInfoMock() {
        Mockito.doNothing().when(orderService).checkParam(Matchers.any());
        Mockito.doNothing().when(orderService).checkOrderExist(Matchers.any());
        orderService.getOrderInfo(-1L);
    }

}

Precautions

  • In the mock method, Matchers.any() must be used as a parameter to generate. If the specific value is executed, the mock will not take effect, and an error may be reported.
  • The parameter method must be a wrapper class of the basic type. Using the basic type will cause problems, because the value that Matchers.any() may generate is null. When assigning to the basic type, it will not be automatically converted to the default value, but will throw a Mockito exception.

Borrow

Use Mockito to mock some methods but not others

Mockito's method

Mockito simulates a method whose return type is void

Implementation of two partial mocks in mockito, spy and callRealMethod

 

Guess you like

Origin blog.csdn.net/yxz8102/article/details/108093664