单元测试(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:数据回滚的意思。所有方法执行完了以后,回滚成原来的样子。在实际的测试代码中,如果将改注解注释掉,数据是不会回滚的。
嚼一路辛苦,饮一路汗水!!
网友评论