单元测试笔记

单元测试(unit test)为了验证程序的正确性
必要性:
预防Bug,快速定位Bug,提高代码质量,减少耦合,减少调试时间,减少重构风险
SpringBoot的测试库.

● Spring Test & Spring Boot Test : SpringBoot提供的应用程序功能集成化测试支持。
● Junit : Java 应用程序单元测试标准类库。
● AssertJ :轻量级的断言类库。
● Hamcrest :对象匹配器类库。
● Mockito : Java Mock 测试框架。
● JsonPath : JSON 操作类库。
JSONassert :用于 JSON 的断言库。
1.了解回归测试框架 JUnit
JUnit 是对程序代码进行单元测试的 Java 框架。ビ用米痈与自切化测试工具,降低
减少烦琐性,并有效避免出现程序错误。
JUnit 测试是白盒测试(因为知道测试如何完成功能和完成什么样的功能)。要使用只需要继承 TestCase 类。


JUnit 提供以下注解。
@ BeforeClass :在所有测试单元前执行一次,一般用来初始化整体的代码。@ AfterClass :在所有测试单元后执行一次,一般用来销毁和释放资源。
@ Before :在每个测试单元前执行,一股用来初始化方法。
@ After :在每个测试单元后执行,一般用来回滚测试数据。.@ Test :编写测试用例。
@ Test ( timeoyt =1000):对测试单元进行限时。这里的“1000”表示若超过1s
测试失败。单位是 m 京尬女子蛋间年一点
@ Test ( expedted = Exception . class ):指定测试单期望得到的异常类。如果执没有抛出指定的异常,则测试失败。
@ Ignore :执行测试时将忽略掉此方法。如果用于修饰类,则忽略整个类。
@ RunWith :在 JUnit 中有很多 Runner ,它们负责调用测试代码。每个 Runner 功能,应根据需要选择不同的 Runner 来运行测试代码。


这里注意:如果Assert.assertThat过期了,那么可以用Hamcrest.assertThat替代
创建单元测试 :
User

package com.example.demo;

import lombok.Data;

/**
 * Copyfright(C),2022-2022,复兴元宇科技有限公司
 * FileName:User Author:yz Date:2022/3/18 19:29
 */
@Data
public class User {
    private String name;
    private int age;
}

UserService

package com.example.demo;

import org.springframework.stereotype.Service;

/**
 * Copyfright(C),2022-2022,复兴元宇科技有限公司
 * FileName:UserService Author:yz Date:2022/3/18 19:30
 */
@Service
public class UserService {
    public User getUserInfo(){
        User user = new User();
        user.setName("wangchaung");
        user.setAge(18);
        return user;
    }
}

HelloController

package com.example.demo;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Copyfright(C),2022-2022,复兴元宇科技有限公司
 * FileName:HelloController Author:yz Date:2022/3/18 19:07
 */
@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String hello(String name){
        return "hello " + name;
    }
}

在Test目录下创建类HelloControllerTest

package com.example.demo;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
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.web.context.WebApplicationContext;

/**
 * Copyfright(C),2022-2022,复兴元宇科技有限公司
 * FileName:HelloControllerTest Author:yz Date:2022/3/18 19:12
 */
public class HelloControllerTest {
    @Autowired
    private WebApplicationContext webApplicationContext;
    private MockMvc mockMvc;

    @Before
    public void setUp() throws Exception{
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

    @Test
    public void hello() throws Exception{
        MvcResult mvcResult = (MvcResult) mockMvc.perform(MockMvcRequestBuilders.get("/hello")
                .contentType("pplication/json;charset=UTF-8")
                .param("wangchuang")
                .accept("pplication/json;charset=UTF-8"))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.content().string("hello wangchuang"))
                .andDo(MockMvcResultHandlers.print())
                .andReturn();
        int status = mvcResult.getResponse().getStatus();
        String content = mvcResult.getResponse().getContentAsString();
        Assert.assertEquals(200,status);
        Assert.assertEquals("hello wangchuang",content);
    }
}

UserServiceTest运行

package com.example.demo;

import org.hamcrest.MatcherAssert;
import org.junit.Assert;
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.regex.Matcher;

import static org.hamcrest.Matchers.is;

/**
 * Copyfright(C),2022-2022,复兴元宇科技有限公司
 * FileName:UserServiceTest Author:yz Date:2022/3/18 19:32
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
    @Autowired
    private UserService userService;
    @Test
    public void getUserInfo(){
        User user = userService.getUserInfo();
        Assert.assertEquals(18,user.getAge());
//        Assert.assertThat(user.getName(),is("wangchuang"));
        MatcherAssert.assertThat("wancghuang",is(user.getName()));
    }
}

控制台打印运行结果:


result.png

Service层单元测试:

User同上
服务类如下:

package com.example.demo.service;

import com.example.demo.entity.User;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    public User getUserInfo(){
        User user = new User();
        user.setName("zhonghua");
        user.setAge(18);
        return user;
    }
}

编写测试:
同上

Respository层的单元测试

Responsitory层主要对数据进行增删改查
Card.class

package com.example.demo.entity;

import lombok.Data;

import javax.persistence.*;

@Entity
@Table(name = "cardtestjpa")
@Data
public class Card {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private Integer num;
 }

CardRepository.interface

package com.example.demo.repository;


import com.example.demo.entity.Card;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CardRepository extends JpaRepository<Card,Long> {
    Card findById(long id);
}

Service

package com.example.demo.service;



import com.example.demo.entity.Card;

import java.util.List;

public interface CardService {
    public List<Card> getCardList();
    public Card findCardById(long id);
}

CardServiceImpl.implements

package com.example.demo.service.impl;


import com.example.demo.entity.Card;
import com.example.demo.repository.CardRepository;
import com.example.demo.service.CardService;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

public class CardServiceImpl implements CardService {
    @Autowired
    private CardRepository cardRepository;

    @Override
    public List<Card> getCardList() {
        return cardRepository.findAll();
    }

    @Override
    public Card findCardById(long id) {
        return cardRepository.findById(id);
    }
}

doTest

package com.example.demo.repository;

import com.example.demo.entity.Card;
import org.junit.After;
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.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;

import static org.junit.Assert.*;

@RunWith(SpringRunner.class)
// SpringJUnit支持,由此引入Spring-Test框架支持!
//启动整个spring的工程
@SpringBootTest
//@DataJpaTest
@Transactional
//@Rollback(false)
public class CardRepositoryTest {
    @Autowired
    private  CardRepository  cardRepository;
    @Test
  public void testQuery() {
   // 查询操作
  List<Card> list = cardRepository.findAll();
        for (Card card : list) {
            System.out.println(card);
        }
   }
    @Test
    public void testRollBank() {
        // 查询操作
        Card card=new Card();

        card.setNum(3);
        cardRepository.save(card);
        //throw new RuntimeException();
    }
}

JPA和MySQL和单元测试junit的依赖

<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>

Applicaiton.properities中关于Mysql的一点配置

spring.datasource.url=jdbc:mysql://127.0.0.1/book?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true
spring.datasource.username=root
spring.datasource.password=rootroot
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql= true

spring.thymeleaf.cache=false
server.port=8080

在IDEA中JPA的实体创建方式

New-JPA-Entity-[Card]
Name:类名字
EntityType:Entity
Id:int
Idgeneration:Identity
Select OK

在IDEA中快速创建Responsitory

New-SpringData-Respository
Entity:上一步创建的[Card]
inputName

其他说明:

@Transactional:数据回滚的意思。所有方法执行完了以后,回滚成原来的样子。在实际的测试代码中,如果将改注解注释掉,数据是不会回滚的。

单元测试中的数据回滚代码

嚼一路辛苦,饮一路汗水!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容