Springboot+H2+Mockito 单元测试,脱离外部MySQL连接

项目场景:

编写代码单元测试为了保证测试环境数据稳定性,使用内嵌数据库H2来代替测试环境数据库


前提:

需注意MySQL导出的sql文件无法适用于H2,具体转换方式详见  https://blog.csdn.net/qionglong_jiao/article/details/117298689

项目准备:

H2建表语句:schema.sql

-- ----------------------------
-- Table structure for app_alarm_year_statistic_single
-- ----------------------------
DROP TABLE IF EXISTS app_alarm_year_statistic_single;
CREATE TABLE app_alarm_year_statistic_single
(
    id                           bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '序号',
    vin                          varchar(17) NOT NULL COMMENT 'vin码',
    oem                          varchar(20) NULL DEFAULT NULL COMMENT '整车厂',
    brand                        varchar(20) NULL DEFAULT NULL COMMENT '品牌',
    car_type                     varchar(20) NULL DEFAULT NULL COMMENT '车型',
    st_date                      char(8) NULL DEFAULT NULL COMMENT '数据日期(yyyyMMdd)',
    running_year                 tinyint(10) UNSIGNED NULL DEFAULT NULL COMMENT '使用年数',
    all_alarm_sum                bigint(255) UNSIGNED NULL DEFAULT NULL COMMENT '所有报警数_总条数',
    temp_diff_alarm_sum          int(255) UNSIGNED NULL DEFAULT NULL COMMENT '温度差异报警_总条数',
    over_temp_alarm_sum          int(255) UNSIGNED NULL DEFAULT NULL COMMENT '电池高温报警_总条数',
    over_voltage_alarm_sum       int(255) UNSIGNED NULL DEFAULT NULL COMMENT '电池过压报警_总条数',
    under_voltage_alarm_sum      int(255) UNSIGNED NULL DEFAULT NULL COMMENT '电池欠压报警_总条数',
    soc_low_alarm_sum            int(255) UNSIGNED NULL DEFAULT NULL COMMENT 'SOC低报警_总条数',
    cell_over_voltage_alarm_sum  int(255) UNSIGNED NULL DEFAULT NULL COMMENT '单体电池过压报警_总条数',
    cell_under_voltage_alarm_sum int(255) UNSIGNED NULL DEFAULT NULL COMMENT '单体电池欠压报警_总条数',
    soc_high_alarm_sum           int(255) UNSIGNED NULL DEFAULT NULL COMMENT 'SOC过高报警_总条数',
    soc_transition_alarm_sum     int(255) UNSIGNED NULL DEFAULT NULL COMMENT 'SOC跳变报警_总条数',
    poor_consistency_alarm_sum   int(255) UNSIGNED NULL DEFAULT NULL COMMENT '单体一致性差报警_总条数',
    insulation_alarm_sum         int(255) UNSIGNED NULL DEFAULT NULL COMMENT '绝缘报警_总条数',
    over_charging_alarm_sum      int(255) UNSIGNED NULL DEFAULT NULL COMMENT '电池过充报警_总条数',
    first_level_alarm_sum        int(255) UNSIGNED NULL DEFAULT NULL COMMENT '一级报警_总条数',
    second_level_alarm_sum       int(255) UNSIGNED NULL DEFAULT NULL COMMENT '二级报警_总条数',
    third_level_alarm_sum        int(255) UNSIGNED NULL DEFAULT NULL COMMENT '三级报警_总条数',
    create_datetime              datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间',
    update_datetime              datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录更新时间',
    PRIMARY KEY (id)
);

H2表数据:data.sql

-- ----------------------------
-- Records of app_alarm_year_statistic_single
-- ----------------------------
DELETE FROM app_alarm_year_statistic_single;
INSERT INTO  app_alarm_year_statistic_single  VALUES (1, '123', 'BAIC', 'BEIJING', 'B01', '20210505', 1, 100, 1, 2, 3, 4, 5, 5, 5, 5, 4, 5, 54, 4, 4, 54, 35, '2021-05-11 15:51:37', '2021-05-14 14:06:27');
INSERT INTO  app_alarm_year_statistic_single  VALUES (2, '123', 'BAIC', 'BEIJING', 'B01', '20210505', 2, 100, 1, 3, 3, 3, 34, 243, 235, 3, 325, 234, 32, 23, 32, 432, 43, '2021-05-11 15:51:37', '2021-05-14 14:06:15');
INSERT INTO  app_alarm_year_statistic_single  VALUES (3, '123', 'BAIC', 'BEIJING', 'B01', '20210505', 3, 100, 1, 3, 3, 3, 34, 243, 235, 3, 325, 234, 32, 23, 32, 432, 43, '2021-05-11 15:51:37', '2021-05-14 14:06:16');
INSERT INTO  app_alarm_year_statistic_single  VALUES (4, '1234', 'BAIC', 'BEIJING', 'B01', '20210505', 3, 100, 1, 3, 3, 3, 34, 243, 235, 3, 325, 234, 32, 23, 32, 432, 43, '2021-05-11 15:51:37', '2021-05-14 14:06:18');

使用内嵌数据库H2:

创建springboot项目

引入依赖:

<!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
<!--h2数据库驱动-->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
<!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

application.yml

spring:
  datasource:
    driver-class-name: org.h2.Driver
    schema: classpath:db/schema.sql #每次启动程序,程序都会运行schema.sql文件,对数据库的数据操作
    data: classpath:db/data.sql #每次启动程序,程序都会运行data.sql文件,对数据库的数据操作
    url: jdbc:h2:mem:test #配置h2数据库的连接地址
    username: test
    password: test

创建实体类:

package com.uaes.battery.fault.monitoring.statistics.domain;


import lombok.Data;

@Data
public class AppAlarmYearStatisticSingleDAO {
    private String vin;
    private String oem;
    private String brand;
    private String carType;
    private Integer runningYear;
    private Integer allAlarm;
    private Integer cellVolOver;
    private Integer cellVolLow;
    private Integer batteryBadConsistency;
    private Integer socOver;
    private Integer socLow;
    private Integer socJump;
    private Integer batteryOver;
    private Integer batteryLow;
    private Integer batteryTempOver;
    private Integer tempDiff;
    private Integer insulation;
    private Integer ressChargeOver;
    private Integer totalVehicle;

}

创建持久层:

package com.uaes.battery.fault.monitoring.statistics.mapper;

import com.uaes.battery.fault.monitoring.statistics.domain.AppAlarmYearStatisticSingleDAO;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface AppAlarmYearStatisticSingleMapper {

    /*
     * 根据条件查询单车故障按照年份的统计结果
     * */

    List<AppAlarmYearStatisticSingleDAO> selectAlarmStatistic(@Param("vin") String vin,
                                                              @Param("stDate") String stDate);
}

持久层实现:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.uaes.battery.fault.monitoring.statistics.mapper.AppAlarmYearStatisticSingleMapper">

    <select id="selectAlarmStatistic"
            resultType="com.uaes.battery.fault.monitoring.statistics.domain.AppAlarmYearStatisticSingleDAO">
        SELECT
        vin,
        oem,
        brand,
        car_type,
        running_year AS runningYear,
        all_alarm_sum AS allAlarm,
        cell_over_voltage_alarm_sum AS cellVolOver,
        cell_under_voltage_alarm_sum AS cellVolLow,
        poor_consistency_alarm_sum AS batteryBadConsistency,
        soc_high_alarm_sum AS socOver,
        soc_low_alarm_sum AS socLow,
        soc_transition_alarm_sum AS socJump,
        over_voltage_alarm_sum AS batteryOver,
        under_voltage_alarm_sum AS batteryLow,
        over_temp_alarm_sum AS batteryTempOver,
        temp_diff_alarm_sum AS tempDiff,
        insulation_alarm_sum AS insulation,
        over_charging_alarm_sum AS ressChargeOver
        FROM
        app_alarm_year_statistic_single
        WHERE
        vin = #{vin}
        <choose>
            <when test="stDate == null">
                AND st_date = (
                SELECT
                MAX(st_date)
                FROM
                app_alarm_year_statistic_single
                WHERE
                vin = #{vin}
                )
            </when>
            <otherwise>
                AND st_date = #{stDate}
            </otherwise>
        </choose>
    </select>


</mapper>

测试类:

package com.uaes.battery.fault.monitoring.statistics.mapper;

import com.alibaba.fastjson.JSONObject;
import com.uaes.battery.fault.monitoring.statistics.domain.AppAlarmYearStatisticSingleDAO;
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.test.context.junit4.SpringRunner;

import java.util.List;


@SpringBootTest
@RunWith(SpringRunner.class)
public class AppAlarmYearStatisticSingleMapperTest {

    @Autowired
    private AppAlarmYearStatisticSingleMapper appAlarmYearStatisticSingleMapper;
    @Test
    public void  selectAlarmStatistic() {
        List<AppAlarmYearStatisticSingleDAO> list =appAlarmYearStatisticSingleMapper.selectAlarmStatistic("123",null);
        System.out.println(JSONObject.toJSON(list));
    }
}

测试结果:

[{"batteryTempOver":2,"cellVolOver":5,"socLow":5,"ressChargeOver":4,"insulation":54,"tempDiff":1,"carType":"B01","allAlarm":100,"socOver":5,"batteryBadConsistency":5,"batteryOver":3,"cellVolLow":5,"oem":"BAIC","runningYear":1,"socJump":4,"batteryLow":4,"vin":"123","brand":"BEIJING"},{"batteryTempOver":3,"cellVolOver":243,"socLow":34,"ressChargeOver":23,"insulation":32,"tempDiff":1,"carType":"B01","allAlarm":100,"socOver":3,"batteryBadConsistency":234,"batteryOver":3,"cellVolLow":235,"oem":"BAIC","runningYear":2,"socJump":325,"batteryLow":3,"vin":"123","brand":"BEIJING"},{"batteryTempOver":3,"cellVolOver":243,"socLow":34,"ressChargeOver":23,"insulation":32,"tempDiff":1,"carType":"B01","allAlarm":100,"socOver":3,"batteryBadConsistency":234,"batteryOver":3,"cellVolLow":235,"oem":"BAIC","runningYear":3,"socJump":325,"batteryLow":3,"vin":"123","brand":"BEIJING"}]

至此说明我们的H2内嵌数据库已经可以代替MySQL跑通持久层的单元测试


Mockito

service:

package com.uaes.battery.fault.monitoring.statistics.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.uaes.battery.fault.monitoring.statistics.domain.*;
import com.uaes.battery.fault.monitoring.statistics.mapper.AppAlarmYearStatisticSingleMapper;
import com.uaes.battery.fault.monitoring.statistics.service.AppAlarmYearStatisticSingleService;
import com.uaes.battery.fault.monitoring.statistics.util.ReturnUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class AppAlarmYearStatisticSingleServiceImpl implements AppAlarmYearStatisticSingleService {

    @Autowired
    private AppAlarmYearStatisticSingleMapper appAlarmYearStatisticSingleMapper;

    @Override
    public Object selectYearAlarmSum(String vin, String stDate) {

        JSONObject result = new JSONObject();
        List<AppAlarmYearStatisticSingleDAO> list = appAlarmYearStatisticSingleMapper.selectAlarmStatistic(vin, stDate);

        if (null != list) {
            ReturnUtil.bulidReturnDataSingle(result, list.get(0).getVin(), list.get(0).getOem(), list.get(0).getBrand(), list.get(0).getCarType(), stDate);
            Map<Integer, AppAlarmYearStatisticSingleDTO> alarmValueMap = list.stream().collect(Collectors.toMap(AppAlarmYearStatisticSingleDAO::getRunningYear, a -> new AppAlarmYearStatisticSingleDTO(a), (k1, k2) -> k2));
            result.put("alarmValue", JSONObject.toJSON(alarmValueMap));
        }

        return result;
    }
}

serviceTest:

package com.uaes.battery.fault.monitoring.statistics.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.uaes.battery.fault.monitoring.statistics.domain.AppAlarmYearStatisticSingleDAO;
import com.uaes.battery.fault.monitoring.statistics.mapper.AppAlarmYearStatisticSingleMapper;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

import java.util.List;

@RunWith(MockitoJUnitRunner.class)
public class AppAlarmYearStatisticSingleServiceImplTest {


    @InjectMocks
    private AppAlarmYearStatisticSingleServiceImpl appAlarmYearStatisticSingleService;

    @Mock
    private AppAlarmYearStatisticSingleMapper appAlarmYearStatisticSingleMapper;

    @Test
    public void selectYearAlarmSum() {
//        模拟appAlarmYearStatisticSingleMapper.selectAlarmStatistic("", ""))的返回值为thenReturn
        List<AppAlarmYearStatisticSingleDAO> thenReturn = JSONArray.parseArray("[{\"batteryTempOver\":2,\"cellVolOver\":5,\"socLow\":5,\"ressChargeOver\":4,\"insulation\":54,\"tempDiff\":1,\"carType\":\"B01\",\"allAlarm\":100,\"socOver\":5,\"batteryBadConsistency\":5,\"batteryOver\":3,\"cellVolLow\":5,\"oem\":\"BAIC\",\"runningYear\":1,\"socJump\":4,\"batteryLow\":4,\"vin\":\"123\",\"brand\":\"BEIJING\"},{\"batteryTempOver\":3,\"cellVolOver\":243,\"socLow\":34,\"ressChargeOver\":23,\"insulation\":32,\"tempDiff\":1,\"carType\":\"B01\",\"allAlarm\":100,\"socOver\":3,\"batteryBadConsistency\":234,\"batteryOver\":3,\"cellVolLow\":235,\"oem\":\"BAIC\",\"runningYear\":2,\"socJump\":325,\"batteryLow\":3,\"vin\":\"123\",\"brand\":\"BEIJING\"},{\"batteryTempOver\":3,\"cellVolOver\":243,\"socLow\":34,\"ressChargeOver\":23,\"insulation\":32,\"tempDiff\":1,\"carType\":\"B01\",\"allAlarm\":100,\"socOver\":3,\"batteryBadConsistency\":234,\"batteryOver\":3,\"cellVolLow\":235,\"oem\":\"BAIC\",\"runningYear\":3,\"socJump\":325,\"batteryLow\":3,\"vin\":\"123\",\"brand\":\"BEIJING\"}]",AppAlarmYearStatisticSingleDAO.class );
        Mockito.when(appAlarmYearStatisticSingleMapper.selectAlarmStatistic("", "")).thenReturn(thenReturn);
//        构建actual
        Object actual = JSON.parseObject("{\"carType\":\"B01\",\"alarmValue\":{\"1\":{\"batteryTempOver\":2,\"cellVolOver\":5,\"socLow\":5,\"ressChargeOver\":4,\"insulation\":54,\"tempDiff\":1,\"allAlarm\":100,\"socOver\":5,\"batteryBadConsistency\":5,\"batteryOver\":3,\"cellVolLow\":5,\"socJump\":4,\"batteryLow\":4},\"2\":{\"batteryTempOver\":3,\"cellVolOver\":243,\"socLow\":34,\"ressChargeOver\":23,\"insulation\":32,\"tempDiff\":1,\"allAlarm\":100,\"socOver\":3,\"batteryBadConsistency\":234,\"batteryOver\":3,\"cellVolLow\":235,\"socJump\":325,\"batteryLow\":3},\"3\":{\"batteryTempOver\":3,\"cellVolOver\":243,\"socLow\":34,\"ressChargeOver\":23,\"insulation\":32,\"tempDiff\":1,\"allAlarm\":100,\"socOver\":3,\"batteryBadConsistency\":234,\"batteryOver\":3,\"cellVolLow\":235,\"socJump\":325,\"batteryLow\":3}},\"oem\":\"BAIC\",\"vin\":\"123\",\"brand\":\"BEIJING\",\"stDate\":\"\"}");
        Assert.assertEquals(appAlarmYearStatisticSingleService.selectYearAlarmSum("", ""),actual);
    }
}

mockito常用方法:


至此一个简要的测试用例已经完成。

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Boot是一个用于构建Java应用程序的开源框架,它提供了一种简化了配置的方式来快速构建应用程序。JUnit是一个用于编写和运行单元测试的开源测试框架,而Mockito是一个用于创建和管理模拟对象的Java库。 下面是一个使用Spring Boot、JUnit和Mockito进行单元测试的示例: 假设我们有一个UserService类,它依赖于一个UserRepository接口来访问数据库并进行一些操作。我们想要对UserService的方法进行单元测试。 首先,我们需要创建一个测试类,命名为UserServiceTest。在测试类中,我们将使用JUnit的注解来标记测试方法,并使用Mockito来创建模拟对象。示例代码如下: ```java @RunWith(MockitoJUnitRunner.class) public class UserServiceTest { @InjectMocks private UserService userService; @Mock private UserRepository userRepository; @Test public void testGetUserById() { // 配置模拟对象的行为 User user = new User("1", "John"); when(userRepository.findById("1")).thenReturn(user); // 调用被测试的方法 User result = userService.getUserById("1"); // 验证结果 assertEquals("John", result.getName()); } } ``` 在上面的示例中,我们使用了@RunWith注解来指定使用MockitoJUnitRunner运行测试,这样就能自动创建和管理模拟对象。使用@InjectMocks注解将被测试的对象自动注入到测试类中,使用@Mock注解创建模拟对象。 在testGetUserById方法中,我们首先使用when方法配置userRepository模拟对象的行为,表示当传入参数为"1",返回一个指定的User对象。 然后,我们通过调用userService的getUserById方法来测试该方法的逻辑。最后,使用assertEquals断言来验证结果是否符合预期。 以上就是一个使用Spring Boot、JUnit和Mockito进行单元测试的示例。通过使用Mockito创建模拟对象,我们可以更容易地测试各个方法的逻辑,而不依赖于实际的数据库。这样可以提高测试效率并确保代码的质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值