SpringBoot整合Spring Data JPA、MySQL、Druid并使用Mockito实现单元测试

一、Maven依赖

<!-- 定义公共资源版本 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.7.RELEASE</version>
    <relativePath />
</parent>

<!-- 设置编码及指定jdk版本 -->
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <druid.version>1.0.29</druid.version>
    <!-- lombock简化代码 -->
    <lombok.version>1.16.20</lombok.version>
</properties>

<!-- 热启动插件 -->
<build>
    <plugins>
        <!-- 支持devtools -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <!-- 没有该配置,devtools不生效 -->
                <fork>true</fork>
            </configuration>
        </plugin>
    </plugins>
</build>

<dependencies>
    <!-- 打war包时加入此项,tomcat相关jar包用外部的不要打进去 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>

    <!-- web项目必要的依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- 单元测试 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!-- 热启动 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
        <scope>true</scope>
    </dependency>

    <!-- spring data jpa -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- mysql数据库 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <!-- alibaba druid -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>${druid.version}</version>
    </dependency>

    <!-- lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${lombok.version}</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

二、配置文件(这里使用yml)

application.yml中:

spring:
  profiles:
    active: dev

application-dev.yml中:

server:
  # 端口号
  port: 8080
spring:
  # 数据源配置
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/spring-dev
    username: root
    password: 123456

    # Druid连接池配置
    type: com.alibaba.druid.pool.DruidDataSource
    # 初始化
    initialSize: 3
    # 最大
    maxActive: 20
    # 最小
    minIdle: 3
    # 最大连接等待超时时间
    maxWait: 60000
    # 打开PSCache,并且指定每个连接PSCache的大小
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    validationQuery: select 'x'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false 
    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis: 60000
    # 配置一个连接在池中最小生存的时间,单位是毫秒
    minEvictableIdleTimeMillis: 300000
    # 配置监控统计拦截的filters,去掉后监控界面sql将无法统计,'wall'用于防火墙
    filters: stat, wall, log4j
  # spring data jpa配置
  jpa:
    hibernate:
      # 实体类有更新时,数据库表更新
      ddl-auto: update
    show-sql: true
    format_sql: true
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
  http:
    # 过滤字符编码
    encoding:
      charset: UTF-8
      enabled: true
      force: true

三、配置代码类

Druid监控

@Configuration
public class DruidConfig {

    @Bean
    public ServletRegistrationBean statViewServlet() {
        // 创建servlet注册实体
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(),
                "/druid/*");
        // 设置ip白名单
        servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
        // 设置ip黑名单,如果allow与deny共同存在时,deny优先于allow
        servletRegistrationBean.addInitParameter("deny", "192.168.0.1");
        // 设置控制台管理用户
        servletRegistrationBean.addInitParameter("loginUsername", "admin");
        servletRegistrationBean.addInitParameter("loginPassword", "123456");
        // 是否可以重置数据
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        return servletRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean statFilter() {
        // 创建过滤器
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
        // 设置过滤器过滤路径
        filterRegistrationBean.addUrlPatterns("/*");
        // 忽略过滤的形式
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        return filterRegistrationBean;
    }

}

四、实体类

学生实体

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "student")
public class StudentEntity implements Serializable {

    /**
     * 序列化ID
     */
    private static final long serialVersionUID = -3967265553147264980L;

    /**
     * 学生id
     */
    @Id
    @GeneratedValue
    private Integer id;

    /**
     * 学生姓名
     */
    private String name;

    /**
     * 学生年龄
     */
    private Integer age;
}

五、dao层

继承自JpaRepository即拥有CRUD
public interface StudentDao extends JpaRepository<StudentEntity, Integer> {

    /**
     * 根据年龄查询学生
     * 
     * @param age
     * @return
     */
    List<StudentEntity> findStudentByAge(Integer age);

    /**
     * 根据年龄获取学生信息 <br>
     * 
     * <@Query是用来配置自定义SQL的注解,后面参数nativeQuery =
     * true才是表明了使用原生的sql,如果不配置,默认是false,则使用HQL查询方式。>
     * 
     * @param age
     * @return
     */
    @Query(value = "select id,name,age from student where age = ?1", nativeQuery = true)
    List<StudentEntity> getStudentByAge(Integer age);

}

六、使用Mocktio进行单元测试

测试基类
/**
 * 测试基类 . <br>
 * ActiveProfiles表示加载指定配置文件 <br>
 * SpringBootTest.WebEnvironment.RANDOM_POR 表示使用随机端口号 <br>
 * Ignore表示本类或本方法不执行测试
 * 
 * @author hkb <br>
 */
@ActiveProfiles("test")
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@Ignore
public class BaseTest {

}
接口测试
public class StudentServiceTest extends BaseTest {

    /**
     * 学生信息接口-被测类
     */
    @Autowired
    private StudentService studentService;

    /**
     * 学生信息dao-模拟对象
     */
    @MockBean
    private StudentDao studentDao;

    /**
     * 学生实体
     */
    private StudentEntity student;

    /**
     * 学生id
     */
    private Integer id = -99;

    /**
     * 学生姓名
     */
    private String studentName = "test";

    /**
     * 学生年龄
     */
    private Integer studentAge = 20;

    /**
     * 所有测试方法执行之前执行该方法
     */
    @Before
    public void before() {
        student = new StudentEntity(id, studentName, studentAge);
        // 设置模拟对象的返回预期值
        Mockito.when(studentDao.save(student)).thenReturn(student);
        Mockito.when(studentDao.findOne(id)).thenReturn(student);
        Mockito.when(studentDao.findStudentByAge(studentAge)).thenReturn(Lists.newArrayList(student));
        Mockito.when(studentDao.getStudentByAge(studentAge)).thenReturn(Lists.newArrayList(student));
        Mockito.when(studentDao.findAll()).thenReturn(Lists.newArrayList(student));
    }

    /**
     * 测试添加
     */
    @Test
    public void addStudentTest() {
        // 执行测试
        int studentId = studentService.addStudent(student);
        // 验证
        Assert.assertThat(studentId, Matchers.is(id));
        // 得到一个抓取器
        ArgumentCaptor<StudentEntity> personCaptor = ArgumentCaptor.forClass(StudentEntity.class);
        // 验证模拟对象的save()是否被调用一次,并抓取调用时传入的参数值
        Mockito.verify(studentDao).save(personCaptor.capture());
        // 获取抓取到的参数值
        StudentEntity addStudent = personCaptor.getValue();
        // 验证调用时的参数值
        Assert.assertThat(studentName, Matchers.is(addStudent.getName()));
    }
}

完整案例请参考:码云

猜你喜欢

转载自blog.csdn.net/hkhhkb/article/details/79789869