Spring Boot Mock数据

栏目: Java · 发布时间: 5年前

内容简介:使用Spring Boot进行微服务或者前后端分离的相关开发设计时,通常使用接口进行对接,而此时就对项目的测试提出了相关要求,比如单元测试,继承测试,调用第三方接口测试等等,达到相应的测试覆盖率;三方接口测试需要自己进行模拟结果返回等,这时就需要Mock相应的数据返回达到测试效果。此处仅仅列举几个比较流行的,还有很多实用的Mock框架,分别有不同的特点,如PowerMock可以实现静态方法,私有方法等方法的mock;相关的mock框架大家可以自行查找,这里给出在项目中,如果不需要对静态方法,私有方法等特殊进

使用Spring Boot进行微服务或者前后端分离的相关开发设计时,通常使用接口进行对接,而此时就对项目的测试提出了相关要求,比如单元测试,继承测试,调用第三方接口测试等等,达到相应的测试覆盖率;三方接口测试需要自己进行模拟结果返回等,这时就需要Mock相应的数据返回达到测试效果。

Mock数据相关

  • Mockito
  • PowerMock
  • TestNG
  • EasyMock
  • etc.

此处仅仅列举几个比较流行的,还有很多实用的Mock框架,分别有不同的特点,如PowerMock可以实现静态方法,私有方法等方法的mock;相关的mock框架大家可以自行查找,这里给出 PowerMock链接 (GitHub).

实践

在项目中,如果不需要对静态方法,私有方法等特殊进行验证测试,则仅仅使用Spring boot自带的Mockito即可完成相关的测试数据Mock,若需要则可以使用PowerMock,简单实用,结合Spring可以使用注解注入;

一些简单的使用这里不再赘述,可以查询相应的文章(基础文章很多),这里主要讲述的是项目中遇到的需要mock调用的第三方接口,在测试Controller层时需要跨层mock封装好的第三方接口返回数据,验证程序是否正确。(如图所示,mock数据跨层)

Spring Boot Mock数据

网上查找很多文章,大部分是重复且无用的基础使用,并无在项目中进行跨层mock数据;跨层mock因涉及到Spring的IOC容器自动注入,所以基础教程的mock不涉及跨层mock,经过实践,总结出已经在项目中使用的Mock操作;

1.使用Mockito(不涉及特殊方法Mock)

由于Mockito集成到Sring Boot的Junit测试之中,使用时不需要特别引入,直接使用即可:(代码如下)

public abstract class AbstractMockBeanTest {

/**
   * BasiceServer封装了对应的三方接口服务,主要是转换接口返回结果数据
   * 使用MockBean注解,自动将IOC容器中需要的对象直接替换成Mock对象,然后Mock相应数据
   */
  @MockBean
  protected BasicServer basicServer;

  /**
   * 如需 basicServer对应的方法需要返回什么类型结果,请在测试前自行调用以下对应方法
   */
  protected void mockGetCarTypeSuccess() {
    String msg = "{\"code\":200,\"data\":{\"businessType\":0,\"capacityType\":0,\"engineType\":0,\"id\":0," +
        "\"seats\":0},\"msg\":\"success\",\"ok\":true}";
    Mockito.when(basicServer.getCarType(anyLong())).thenReturn(msg);
  }

  protected void mockGetCarTypeSuccessNoData() {
    String msg = "{\"code\":200,\"msg\":\"success\",\"ok\":true}";
    Mockito.when(basicServer.getCarType(anyLong())).thenReturn(msg);
  }


  protected void mockGetCitySuccess() {
    String msg = "{\"code\":200,\"data\":{\"businessType\":0,\"capacityType\":0,\"engineType\":0,\"id\":0," +
        "\"seats\":0},\"msg\":\"success\",\"ok\":true}";
    Mockito.when(basicServer.getCityByCode(anyString())).thenReturn(msg);
  }

  protected void MockGetCitySuccessSuccessNoData() {
    String msg = "{\"code\":200,\"msg\":\"success\",\"ok\":true}";
    Mockito.when(basicServer.getCityByCode(anyString())).thenReturn(msg);
  }
}

复制代码

2.使用PowerMock(可对特殊方法Mock)

因为跨层,当测试代码使用IOC容器自动注入相应对象时,需要手动指定将自动注入的对象替换为自己Mock的对象,才能生效;替换过程使用反射指定。(代码如下)

package cn.skio.capacity.apis.v1;

import cn.skio.capacity.application.impl.CarServiceImpl;
import cn.skio.capacity.third.basic.v1.BasicService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.hamcrest.core.Is;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.util.ReflectionTestUtils;
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 java.util.Optional;

import static org.mockito.ArgumentMatchers.anyLong;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.handler;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

/**
 * @author Jasmine
 * @date 19/06/19
 */
@ActiveProfiles("test")
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({BasicService.class})
@PowerMockIgnore({"javax.management.*", "javax.net.ssl.*"})
@SpringBootTest
public class TestController {
  @Autowired
  private WebApplicationContext context;

  private MockMvc mvc;

  @Mock
  private BasicService basicService;

  @Autowired
  private CarServiceImpl carService;

  @Before
  public void setUp() throws Exception {
    mvc = MockMvcBuilders.webAppContextSetup(context).build();
    // 使用反射将IOC容器注入的service的属性替换指定为mock的对象
    ReflectionTestUtils.setField(carService, "basicService", basicService);
    PowerMockito.when(this.basicService, "getCarType", anyLong()).thenReturn(Optional.empty());
  }

  @Test
  @Transactional
  public void testA() throws Exception {
        MvcResult result = mvc.perform(MockMvcRequestBuilders.get("/v1/cars")
            .contentType(MediaType.APPLICATION_JSON_UTF8)
            .accept(MediaType.APPLICATION_JSON)
    ).andExpect(status().isOk())
            .andExpect(handler().handlerType(CarController.class))
            .andExpect(handler().methodName("search"))
            .andDo(MockMvcResultHandlers.print())
            .andReturn();
    JSONObject object = JSON.parseObject(result.getResponse().getContentAsString(), JSONObject.class);
    Assert.assertThat("数据量不是2", object.getJSONObject("data").getJSONArray("list").size(), Is.is(2));
  }
}

复制代码

总结

PowerMock相比Mockito提供更多的Mock方法,使用相对灵活,推荐使用。

使用PowerMock现在对应的gradle依赖为,使用powermock-api-mockito2,不要使用powermock-api-mockito:

testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.2'
testCompile group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.2'
testCompile group: 'org.mockito', name: 'mockito-core', version: '2.28.2'
复制代码

详细的可以参考以下链接:

  1. PowerMock
  2. 版本对接

以上所述就是小编给大家介绍的《Spring Boot Mock数据》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Tagging

Tagging

Gene Smith / New Riders / 2007-12-27 / GBP 28.99

Tagging is fast becoming one of the primary ways people organize and manage digital information. Tagging complements traditional organizational tools like folders and search on users desktops as well ......一起来看看 《Tagging》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具