使用MockMvc进行controller层单元测试 事务自动回滚的完整案例

看代码吧~

package com.ieou.ms_backend.controller;
import com.google.gson.Gson;
import com.ieou.ms_backend.dto.account.CreateAccountReq;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MockMvcBuilder;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.WebApplicationContext;
import static org.junit.Assert.*;
/**
 * created by wyz on 2019/5/6
 */
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class AccountControllerTest {
    @Autowired
    private WebApplicationContext wac;
    private MockMvc mockMvc;
    private String url = "/ms_backend/account/";
    @Before
    public void setUp() throws Exception{
        //初始化MockMvc对象
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }
    //GET 请求
    @Test
    public void accountList() throws Exception {
        MockHttpServletRequestBuilder mockHttpServletRequestBuilder = MockMvcRequestBuilders.get(url + "accountList")
                .param("companyName", "wang")
                .header("access_token", "accessToken");
        mockHttpServletRequestBuilder.accept(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON_UTF8);
        ResultActions resultActions = mockMvc.perform(mockHttpServletRequestBuilder);
        resultActions.andReturn().getResponse().setCharacterEncoding("UTF-8");
        resultActions.andExpect(MockMvcResultMatchers.status().isOk());
        resultActions.andDo(MockMvcResultHandlers.print());
    }
    @Test
    public void removeAccount() {
    }
    //post 请求  @RequestBody
    @Test
    @Transactional
    @Rollback() // 事务自动回滚,默认是true。可以不写
    public void createAccount() throws Exception {
        CreateAccountReq req = new CreateAccountReq();
        MockHttpServletRequestBuilder mockHttpServletRequestBuilder = MockMvcRequestBuilders.post(url + "createAccount")
                .header("access_token", "accessToken");
        mockHttpServletRequestBuilder.accept(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .content(new Gson().toJson(req)); // post请求
        ResultActions resultActions = mockMvc.perform(mockHttpServletRequestBuilder);
        resultActions.andReturn().getResponse().setCharacterEncoding("UTF-8");
        resultActions.andExpect(MockMvcResultMatchers.status().isOk());
        resultActions.andDo(MockMvcResultHandlers.print());
    }
}

Spring-test 单元测试数据不自动回滚的解决方案

在使用JUnit做单元测试时,为了使测试数据不对数据库造成污染,故选取了spring-test进行单元测试,但在进行dao层的测试时,发现save方法无法进行数据的自动回滚。

逐一进行检查分析,事务也开启了,并使用注解方式标记@RollBack(true),在控制台中也打出了事务回滚的信息,但仍然不能自动回滚。

后来感觉是数据库的原因,我的数据库使用的是MySql,这就存在数据表的类型是否支持事务情况。

逐查阅MySql相关文档,发现,InnoDB类型的表是支持事务的,而MyISAM是不支持事务的,立刻查看数据表类型,果然为MyISAM,改为InnoDB后,重新进行测试,问题得到解决。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • SpringBoot MockMvc单元测试的示例代码

    为何使用MockMvc? 对模块进行集成测试时,希望能够通过输入URL对Controller进行测试,如果通过启动服务器,建立http client进行测试,这样会使得测试变得很麻烦,比如,启动速度慢,测试验证不方便,依赖网络环境等,所以为了可以对Controller进行测试,我们引入了MockMVC. MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快.不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而

  • spring-mvc/springboot使用MockMvc对controller进行测试

    网上基本都是参考官方的使用方式,使用了import static,个人感觉这种方式特别不好,代码提示性不友好.所以在此进行说明,也方便自己以后使用. 1. 引入spring-test相关jar包,springboot只需引入spring-boot-starter-test即可 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tes

  • Spring Boot从Controller层进行单元测试的实现

    单元测试是程序员对代码的自测,一般公司都会严格要求单元测试,这是对自己代码的负责,也是对代码的敬畏. 一般单元测试都是测试Service层,下面我将演示从Controller层进行单元测试. 无参Controller单元测试示例: package com.pingan.bloan.genesis.controller.base; import org.junit.After; import org.junit.Before; import org.junit.runner.RunWith; im

  • 详解Spring MVC如何测试Controller(使用springmvc mock测试)

    在springmvc中一般的测试用例都是测试service层,今天我来演示下如何使用springmvc mock直接测试controller层代码. 1.什么是mock测试? mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法. 2.为什么要使用mock测试? 使用Mock O bject进行测试,主要是用来模拟那些在应用中不容易构造(如HttpServletRequest必须在Servlet容器中才能构造出来)或者比较复杂的对象(如J

  • 使用MockMvc进行controller层单元测试 事务自动回滚的完整案例

    看代码吧~ package com.ieou.ms_backend.controller; import com.google.gson.Gson; import com.ieou.ms_backend.dto.account.CreateAccountReq; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.fact

  • 完美解决Spring声明式事务不回滚的问题

    疑问,确实像往常一样在service上添加了注解 @Transactional,为什么查询数据库时还是发现有数据不一致的情况,想想肯定是事务没起作用,出现异常的时候数据没有回滚.于是就对相关代码进行了一番测试,结果发现一下踩进了两个坑,确实是事务未回滚导致的数据不一致. 下面总结一下经验教训: Spring事务的管理操作方法 编程式的事务管理 实际应用中很少使用 通过使用TransactionTemplate 手动管理事务 声明式的事务管理 开发中推荐使用(代码侵入最少) Spring的声明式事

  • MySql事务无法回滚的原因有哪些

    使用MySQL时,如果发现事务无法回滚,但Hibernate.Spring.JDBC等配置又没有明显问题时,不要苦恼,先看看MySQL创建的表有没有问题,即表的类型. InnoDB和MyISAM是在使用MySQL最常用的两个表类型,各有优缺点,视具体应用而定.基本的差别为:MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持.MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持已经外部键等高级数据库功能. MyIASM是I

  • spring事务异常回滚实例解析

    最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug?我想多了....... 为了打印清楚日志,很多方法我都加tyrcatch,在catch中打印日志.但是这边情况来了,当这个方法异常时候日志是打印了,但是加的事务却没有回滚. 例: 类似这样的方法不会回滚(一个方法出错,另一个方法不会回滚): if(userSave){ try { userDao.save(user); userCapabilityQuotaDao.save(capabilityQuota); } catch (Exce

  • SpringBoot事务不回滚的解决方案

    目录 1.非 public 方法解决方案 2.try/catch 解决方案 解决方案1:将异常重新抛出 解决方案2:使用代码手动回滚事务 3.调用内部 @Transactional 方法解决方案 4.检查异常的事务解决方案 5.数据库不支持事务的解决方案 总结 在 Spring Boot 中,造成事务不自动回滚的场景有很多,比如以下这些: 非 public 修饰的方法中的事务不自动回滚: 当 @Transactional 遇上 try/catch 事务不自动回滚: 调用类内部的 @Transac

  • 解决@Transactional注解事务不回滚不起作用的问题

    这几天在项目里面发现我使用@Transactional注解事务之后,抛了异常居然不回滚.后来终于找到了原因. 如果你也出现了这种情况,可以从下面开始排查. 一.特性 先来了解一下@Transactional注解事务的特性吧,可以更好排查问题 1.service类标签(一般不建议在接口上)上添加@Transactional,可以将整个类纳入spring事务管理,在每个业务方法执行时都会开启一个事务,不过这些事务采用相同的管理方式. 2.@Transactional 注解只能应用到 public 可

  • 详解Java子线程异常时主线程事务如何回滚

    一.提出问题 最近有一位朋友问了我这样一个问题,问题的截图如下: 这个问题问的相对比较笼统,我来稍微详细的描述下:主线程向线程池提交了一个任务,如果执行这个任务过程中发生了异常,如何让主线程捕获到该异常并且进行事务的回滚. 二.主线程与子线程 先来看看基础,下图体现了两种线程的运行方式, 左侧的图,体现了主线程启动一个子线程之后,二者互不干扰独立运行,生死有命,从此你我是路人! 右侧的图,体现了主线程启动一个子线程之后继续执行主线程程序逻辑,在某一节点通过阻塞的方式来获取子线程的执行结果. 对于

  • SpringMVC中事务是否可以加在Controller层的问题

    目录 SpringMVC中事务是否可以加在Controller层 Spring在Controller层的事务操作 以下是代码 SpringMVC中事务是否可以加在Controller层 一般而言,事务都是加在Service层的,但是爱钻牛角尖的我时常想:事务加在Controller层可不可以. 我一直试图证明事务不止可以加在Service层,还可以加在Controller层,但是没有找到有力的论据来支持我这个想法,搞得我一度认为事务只能加在Service层,直到我读过spring官方文档并实践之

  • SSM如何实现在Controller中添加事务管理

    目录 SSM在Controller中添加事务管理 1.在controller层写编程式事务[繁琐,不推荐] 2.将事务配置定义在SpringMVC的应用上下文(spring-mvc.xml)中[简单明了.一劳永逸] SSM下Controller层的事务配置问题 解决 为什么会这样? SSM在Controller中添加事务管理 本人使用: 集成开发环境:idea 项目管理工具:maven 数据库:oracle 框架:Spring+SpringMVC+myBatis 一般而言,事务都是加在Servi

  • spring声明式事务 @Transactional 不回滚的多种情况以及解决方案

    目录 一. spring 事务原理 问题一.@Transactional 应该加到什么地方,如果加到Controller会回滚吗? 问题二. @Transactional 注解中用不用加rollbackFor = Exception.class 这个属性值 问题三:事务调用嵌套问题具体结果如下代码: 四.总结 五. 参考链接 本文是基于springboot完成测试测试代码地址如下: https://github.com/Dr-Water/springboot-action/tree/master

随机推荐