引入依赖的包:

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.23.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>2.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.2</version>
<scope>test</scope>
</dependency>

MockMvc + PowerMock + Mockito 来模拟post get请求,并mock掉service中存在doGet doPost外部系统的restful请求

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@prepareForTest({
HttpUtil.class // doGet doPost 使用util类,这里需要告诉UT
})
@PowerMockIgnore("javax.crypto.*")
@AutoConfigureMockMvc
@SpringBootTest
public class DemoSzlTest {
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc; @Before
public void setUp() throws Exceptioin {
MockitoAnnotations.initMocks(this); // 初始化装载powerMockito
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
} @Test
@DirtiesContext
public void testPostDemo() throws Exception {
// mock HttpResponse 对象返回
StringEntity se = new StringEntity("xxxxxx", "utf-8");
HttpResponse resp = new BasicHttpResponse(new BasicStatusLine(HttpVersion.Http_1_1, HttpServletResponse.SC_OK, ""));
resp.setEntity(se);
PowerMockito.mockStatic(HttpUtil.class);
// 这里的 Mockito.anyString() 要和 实际方法参数保持一致
PowerMockite.when(HttpUtil.doGet(Mockito.anyString(), Mockito.anyMap(), Mockito.any())).thenReturn(resp);
// 这里不 mock方法,直接走真实场景方法
PowerMockito.when(HttpUtil.toJson(Mockito.anyObject())).thenCallRealMethod();
// body contents
String jsonBody = "{\"aaaa\":\"1111\"}";
String token = "xxxxx";
MvcResult resultMsg = mockMvc.perform(
post("/xxx")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.accept(MediaType.APPLICATION_JSON_UTF8_VALUE)
.header("xxxxx", token)
.content(jsonBody) // request body
).andExpect(status().isCeated())
.andReturn();
}     @Test
    @DirtiesContext
    public void contextLoads() throws Exception {
        // 这里定义的 header 值 必须要和service层使用的值保持一致,否则powerMock mock时会有问题
        // 其实也很好理解,既然要mock,那就做到真实一点,一切都保持一模一样即可。
        Header[] header = {
                new BasicHeader("Authorization", "aaabbbccc"),
                new BasicHeader("Content-Type", "application/json")
            };
        
        // 手动创建HttpResponse,来模式http请求的返回值
        StringEntity se = new StringEntity("{"
                + "\"memo\":\"这个只是demo式样\"}", "utf-8");
        HttpResponse resp = new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1,
                HttpServletResponse.SC_OK, ""));
        resp.setEntity(se);
        
        // 和上面说明一致
        StringEntity se2 = new StringEntity("{"
                + "\"memo\":\"这个只是demo2式样\"}", "utf-8");
        HttpResponse resp2 = new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1,
                HttpServletResponse.SC_OK, ""));
        resp2.setEntity(se2);
        
        // 开始mock我们想要的静态方法,此处是mock post请求并返回上面我们mock的值
        PowerMockito.mockStatic(HttpUtil.class);
        /**
         * 本人是为了达到一个service里连续调用2次post请求,但2次请求内容不同,返回结果也不同,进行mock
         * Mockito.eq("/aaa")               是mock值
         * Mockito.eq("aaabbb")             是mock值
         * Mockito.any(header.getClass())   是mock Header[]值
         */
        PowerMockito.when(HttpUtil.doPost(Mockito.eq("/aaa"), Mockito.eq("aaabbb"), Mockito.any(header.getClass()))).thenReturn(resp);
        PowerMockito.when(HttpUtil.doPost(Mockito.eq("/bbb"), Mockito.eq("cccddd"), Mockito.any(header.getClass()))).thenReturn(resp2);
        
        String jsonBody = "{\"aaaa\":\"1111\"}";
        String token = "xxxxx";
        MvcResult resultMsg = mockMvc.perform(
                 post("/testUTDemo")
                 .header("Authorization", token)
                 .content(jsonBody)    // request body
        ).andExpect(status().isCreated()).andReturn();
    } }

Controller类:

package com.szl.demo.szldemo.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.szl.demo.szldemo.common.dto.UserDto;
import com.szl.demo.szldemo.service.UserService;
import lombok.extern.slf4j.Slf4j; @Slf4j
@Controller
public class DemoController {
@Autowired
private UserService userService; @ResponseBody
@RequestMapping(value = "/testUTDemo", method = RequestMethod.POST)
public UserDto testUTDemo(HttpServletRequest request, HttpServletResponse response) {
return userService.testDemoUnitTest();
} }

Service接口:

package com.szl.demo.szldemo.service;

import com.szl.demo.szldemo.common.dto.UserDto;

public interface UserService {

    UserDto testDemoUnitTest();

}

Service实现类:

package com.szl.demo.szldemo.service.impl;

import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.message.BasicHeader;
import org.springframework.stereotype.Service;
import com.szl.demo.szldemo.common.dto.UserDto;
import com.szl.demo.szldemo.common.util.HttpUtil;
import com.szl.demo.szldemo.service.UserService;
import lombok.extern.slf4j.Slf4j; @Slf4j
@Service("userService")
public class UserServiceImpl implements UserService { public UserDto testDemoUnitTest() {
try {
Header[] header = {
new BasicHeader("Authorization", "aaabbbccc"),
new BasicHeader("Content-Type", "application/json")
};

// 此处的代码块也是mock的重点
HttpResponse resp = HttpUtil.doPost("/aaa", "aaabbb", header);
HttpEntity entity = resp.getEntity();
String msg = IOUtils.toString(entity.getContent(), "UTF-8");
log.info("msg: " + msg);

// 同上
HttpResponse resp2 = HttpUtil.doPost("/bbb", "cccddd", header);
HttpEntity entity2 = resp2.getEntity();
String msg2 = IOUtils.toString(entity2.getContent(), "UTF-8");
log.info("msg2: " + msg2);
} catch (Exception e) {
e.printStackTrace();
}

// 这里随便赋值并返回,主要不是看这里的功能
UserDto dto = new UserDto();
dto.setId(1001L);
dto.setNickName("test");
dto.setUserId(10000001L);
return dto;
} }

HttpUtil.java类:

public class HttpUtil {
public static HttpResponse doGet(String url, Map<String, String> params, Header[] headers) {
.....
这里省略
} public static JsonObject toJson(HttpResponse httpResponse) {
.....
这里省略
}
public static HttpResponse doPost(String url, String params, Header[] header) {
        // 这里只是为了演示,手动创建StringEntity并赋值,手动创建HttpResponse并返回
        HttpResponse resp = new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, null));
        StringEntity se1 = new StringEntity("{"
                + "\"alg\":\"aqas\","
                + "\"id\":\"122011\"}", "utf-8");
        resp.setEntity(se1);
        return resp;
}
}

UserDto类:

package com.szl.demo.szldemo.common.dto;

import java.io.Serializable;
import lombok.Data; @Data
public class UserDto implements Serializable {
private static final long serialVersionUID = -8858511759866491158L; private Long id;
private Long userId;
private String nickName; }

好了,让咋们来试试上面的UT跑出什么结果,如下图:

OK, 大功告成,如有博友需要,供参考,需转发,请注明引自链接,谢谢。

另附上额外功能,如果有朋友需要在UT里按顺序执行,需要加注解:

@FixMethodOrder(xxx)

这里的xxx有三种模式:

- 默认(MethodSorters.DEFAULT)
- 按方法名(MethodSorters.NAME_ASCENDING)
- JVM(MethodSorters.JVM)

一开始本人使用JVM模式,虽然能达到预期,但运行不太稳定,本人还是推荐大家使用NAME_ASCENDING模式

如有朋友参考本人的笔记,有问题可以留言,转载请注明原著,谢谢。

springboot2.1.3+Junit4 单元测试的更多相关文章

  1. SpringBoot使用Junit4单元测试

    SpringBoot2.0笔记 本篇介绍Springboot单元测试的一些基本操作,有人说一个合格的程序员必须熟练使用单元测试,接下来我们一起在Springboot项目中整合Junit4单元测试. 本 ...

  2. JUnit4 单元测试

    一. 题目简介 这次的单元测试我作了一个基本运算的程序,该程序实现了加,减,乘,除,平方,倒数的运算,该程序进行测试比较的简单,对于初步接触JUnit的我来说测试起来也比较容易理解. 二.源码的git ...

  3. Junit4单元测试

    在Eclipse中使用JUnit4进行单元测试(初级篇) 在Eclipse中使用JUnit4进行单元测试(中级篇) 在Eclipse中使用JUnit4进行单元测试(高级篇)

  4. JUnit4单元测试基础篇

    引言 JUnit作为Java语言的测试框架,在测试驱动开发(TDD)下扮演重要的角色.众所周知,无论开发大型项目还是一般的小型项目, 单元测试都至关重要.单元测试为软件可发测试维护提供了很大的便利.J ...

  5. Spring 下使用Junit4 单元测试

    package platform; import java.util.List; import java.util.UUID; import javax.annotation.Resource; im ...

  6. Junit4单元测试的基本用法

    看了一些Junit4的视频,简单了解了Junit4的一些基本用法,整理记录一下. 环境搭建 这里使用的开发工具是MyEclipse,首先新建一个Java工程,将Junit4的jar包引入,eclips ...

  7. Method 'initializationerror' not found.Opening the test classs JUnit4单元测试报错问题解决办法(图文详解)

    不多说,直接上干货! 问题现象 今天使用JUnit 4进行单元测试时,测试程序一直运行不起来,报method initializationerror not found错误,如下: 问题分析 网上说版 ...

  8. JUnit4单元测试入门教程

    本文按以下顺序讲解JUnit4的使用 下载jar包 单元测试初体验 自动生成测试类 执行顺序 @Test的属性 下载jar包## 下载地址 在github上,把以下两个jar包都下载下来.     下 ...

  9. Java Web(5) Spring 下使用Junit4 单元测试

    1. 如何在不启动Tomcat服务器的情况下对,Dao这些不依赖使用Servlet API的类来进行单元测试呢? 其实在Spring框架体系中,已经有一套自己的测试代码,其中就是依赖使用Junit来进 ...

随机推荐

  1. Android 编译 product 分区

    https://source.android.google.cn/devices/bootloader/product-partitions 编译 product 分区 Android 9​ 支持使用 ...

  2. 如何查看Linux服务器是32位还是64位?

    使用命令 “getconf LONG_BIT” 如果返回的是32,那么就是32位 如果返回的是64,那么就是64位

  3. 软件定义网络基础---REST API概述

    一:什么是REST API REST API是北向接口的主流设计方式 API是应用程序编程接口,是预先定义好的函数,可以供应用程序或开发人员访问调用 年 Roy Thomas Fielding 的博士 ...

  4. BladeX 2.0.7.RELEASE版本git后,在idea中导入项目,结果无法运行FlowApplication等几个服务的错误

    问题:2.0.7.RELEASE版本git后,在Intellij IDEA运行项目,结果无法运行FlowApplication等几个服务的错误 描述:打开IDEA,点击Check out from V ...

  5. [LeetCode] 602. Friend Requests II: Who Has Most Friend? 朋友请求 II: 谁有最多的朋友?

    In social network like Facebook or Twitter, people send friend requests and accept others' requests ...

  6. JIT(just in time)即时编译器

    JIT(just in time) 前端vs后端 在编译原理中,通常将编译分为前端和后端.其中前端会对程序进行词法分析.语法分析.语义分析,然后生成一个中间表达形式(称为IR:Intermediate ...

  7. java的单进程多线程模式

    java是单进程多线程模型,多线程依然可以充分利用多核(core)/多处理器(cpu) 单个cpu线程在同一时刻只能执行单一指令,也就是一个线程 单个线程同时只能在单个cpu线程中执行 Java中的所 ...

  8. 在使用FPGA来控制DDR3/DDR2 IP 的时候两个错误的解决办法

    对于熟悉Intel FPGA的老(gong)司(cheng)机(shi)来说,外部存储器的控制早已是轻车熟路,但是对于新手,DDR3/DDR2 的IP使用也许并没有那么简单,不过没关系,骏龙的培训网站 ...

  9. Springboot项目中异常拦截设计与处理

    背景: 项目运行过程中会出现各种各样的问题,常见的有以下几种情况: 业务流程分析疏漏,对业务流程的反向操作.边界分析设计不充分 调用外部服务.调用外部系统出现的超时.错误.返回值与预期不符 外部资源连 ...

  10. vscode failed to excute git

    将代码提交到github时 提示 “failed to excute git” 解决:配置git git config --global user.email "youremailid@ex ...