通俗学习Mockito结合Spring跨多层接口mock测试方法

通俗学习Mockito结合Spring跨多层接口mock测试方法

1、场景:A调B,B调C,测试A,mock掉C

想要测试ServiceA服务的getUserVo()方法,而getUserVo()方法调用了ServiceB服务,ServiceB又调用了ServiceC服务的getUser()方法,需要mock掉ServiceC的getUser()方法。

2、操作方法: 详细如代码,参照代码注释

  1. 把需要mock注入的服务ServiceA,ServiceB加上@InjectMocks
  2. 把需要mock的服务ServiceC加上@Mock@Spy
  3. 执行测试方法前@Before初始化Mock注入,加上MockitoAnnotations.initMocks(this);
  4. 调用测试接口前执行需要mock的方法,指定mock的返回值 when(serviceC.getUser(anyInt())).thenReturn(user);
//手动导入static的Mockito包
import static org.mockito.Mockito.*;

@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/spring-config.xml")
public class MockTest {
    //需要mock注入的服务
    @InjectMocks
    @Autowired
    private ServiceA serviceA;
    //需要mock注入的服务
    @InjectMocks
    @Autowired
    private ServiceB serviceB;
    //需要mock掉的服务
    @Mock
    @Autowired
    private ServiceC serviceC;
    //初始化mock注入
    @Before
    public void initMock() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void test() {
        User user = new User();
        user.setId(1);
        user.setName("张三");
        //指定当调用ServiceC.getUser()时返回的user对象
        when(serviceC.getUser(anyInt())).thenReturn(user);
        /*
         * serviceA -> serviceB -> serviceC
         * 这里serviceA.getUserVo()里调用serviceB.getUserDto()方法,
         * serviceB里又调用serviceC.getUser()方法,mock掉serviceC的getUser()方法
         */
        UserVo userVo = serviceA.getUserVo("123");
        log.info(JSONObject.toJSONString(userVo)); // UserVo(1, "张三")
    }
}

3、扩展:

  1. @Mock@Spy的区别:

    • @Mock如果不写形如when(...).thenReturn(...)的打桩,服务下的所有属性方法将返回0或null;
    • @Spy不写when(...).thenReturn(...)打桩则是按真实的代码执行。
  2. when(...).thenReturn(...)doReturn(..).when(...)的区别:

    • 两者都返回mock结果,前者会调用真实代码后返回mock结果,后者直接返回mock结果。
    • 用法区别:when(serviceA.getUser(anyInt())).thenReturn(user)doReturn(user).when(serviceA).getUser(anyInt())

版权声明:本文为fqfa1226原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。