引入依赖的包:

<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. 决策树分析、EMV(期望货币值)

    名称:决策树分析.EMV(期望货币值) 定义:它利用了概率论的原理,并且利用一种树形图作为分析工具.其基本原理是用决策点代表决策问题,用方案分枝代表可供选择的方案,用概率分枝代表方案可能出现的各种结果 ...

  2. EF Core基本使用

    Mysql: nuget 安装 Pomelo.EntityFrameworkCore.MySql Microsoft.EntityFrameworkCore.Design csprj 修改: < ...

  3. [LeetCode] 236. Lowest Common Ancestor of a Binary Tree 二叉树的最近公共祖先

    Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...

  4. Go语言中的值类型和引用类型

    一.值类型和引用类型值类型:int.float.bool和string这些类型都属于值类型,使用这些类型的变量直接指向存在内存中的值,值类型的变量的值存储在栈中.当使用等号=将一个变量的值赋给另一个变 ...

  5. python实践项目九:操作文件-修改文件名

    描述:多个文件,文件名名包含美国风格的日期( MM-DD-YYYY),需要将它们改名为欧洲风格的日期( DD-MM-YYYY) 代码1:先创建100个文件名为美国风格日期的文件(文件路径为项目当前路径 ...

  6. python基础教程(2)

    Python 基础教程 Python 是一种解释型.面向对象.动态数据类型的高级程序设计语言. 执行Python程序 对于大多数程序语言,第一个入门编程代码便是 "Hello World!& ...

  7. LeetCode 82. 删除排序链表中的重复元素 II(Remove Duplicates from Sorted List II)

    82. 删除排序链表中的重复元素 II 82. Remove Duplicates from Sorted List II 题目描述 给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中没有 ...

  8. 从Asp .net到Asp core (第一篇)《回顾Asp .net生命周期与管道机制》

    从2016年微软收购了Xamarin整合到Visual Studio里并将其开源到现在已有三年多时间,从.net core 1.0 到现在的2.2,以及即将问世的3.0,我们看到微软正在跨平台之路越走 ...

  9. 04 javascirpt基础知识---听课笔记

    1.JavaScript概念 一门客户端脚本语言运行在客户端浏览器中的.每一个浏览器都有JavaScript的解析引擎脚本语言:不需要编译,直接就可以被浏览器解析执行了 * 功能:可以来增强用户和ht ...

  10. Java开发环境的搭建02——IntelliJ IDEA篇(Windows)

    1.IntelliJ IDEA的下载与安装 IntelliJ IDEA简称IDEA,由JetBrains公司开发,是java语言开发的集成环境,也是目前业界被公认的最好的java开发工具之一.尤其在智 ...