maven项目进行单元测试详细教程
-
-
- 为什么使用mock
-
举个例子:
类 A 需要调用类 B 和类 C,而类 B 和类 C 又需要调用其他类如 D、E、F 等,假设类 D 是一个外部服务,那就会很难测,因为你的返回结果会直接的 受外部服务影响,导致你的单元测试可能今天会过、但明天就过不了了。
而当我们引入 Mock 测试时,就可以创建一个假的对象,替换掉真实的 Bean B 和 C,这样在调用B、C的方法时,实际上就会去调用这个假的 Mock 对象的方法,而我们就可以自己设定这个 Mock 对象的参数和期望结果,让我们可以专注在测试当前的类 A,而不会受到其他的外部服务影响,这样测试效率就能提高很多。
比如你现在想要测试一个方法是否是正常的,但是这个方法中有很多调用数据库的代码,那么我们就可以在每个调用数据库的地方打桩,模拟一下访问完数据库之后的返回值,这样我们就可以在测试的时候避免访问数据库了,可以非常高效地完成我们的单元测试,已达到验证我们写的方法到底对不对的目的。
mockB=mock(B.class);
mockC=mock(C.class);
-
-
- 新建maven项目
-
File->new->project->maven->Project SDK 已经正确配置,通常为jdk版本-》如果需要,可以勾选 Create from archetype,并选择一个 Maven 原型(archetype),比如 maven-archetype-quickstart 用于快速创建一个简单的 Maven 项目
- GroupId: 输入项目的组织或公司名称(如 com.example )。
- ArtifactId: 输入项目的名称(如 my-maven-project)。
- Version: 输入项目的版本号(默认为 1.0-SNAPSHOT)。
- Project name: 输入项目在 IDEA 中的显示名称。
- Project location: 选择项目保存的路径。
直接finlish,IDEA 会自动下载 Maven 依赖并构建项目。你可以在底部的 Maven 工具窗口中查看进度。
创建完成后,项目结构如下:
- src/main/java: 存放 Java 源代码。
- src/test/java: 存放测试代码。
- pom.xml: Maven 项目的核心配置文件。
-
- 运行项目
-
- 在 src/main/java 中创建一个简单的 Java 类,并编写 main 方法。
- 右键点击类文件,选择 Run 来运行程序。
-
- 管理依赖
-
- 如果需要添加依赖,可以在 pom.xml 文件的 <dependencies> 标签中添加依赖项,IDEA 会自动下载并管理这些依赖。
-
- 找不到类junit
-
删除C:\Users\<你的用户名>\.m2\repository\org\junit\junit 文件夹,maven-->clean一下
-
-
- 单元测试a+b简单案例
-
目录结构:
App.java类
package org.example;
public class App {
public static int add(int a, int b) {
return a + b;
}
}
AppTest.java类
package org.example;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class AppTest {
@Test
void testAdd() {
assertEquals(5, App.add(2, 3));
}
}
配置文件pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>dycs</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- JUnit 5 API -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<!-- JUnit 5 引擎 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<!-- JUnit 平台引擎 -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-engine</artifactId>
<version>1.10.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
运行AppTest.java,结果
-
-
- 生成测试用例的快捷键
-
CTRL+shift+t
-
-
- mock使用when控制行为(方法)返回值
-
@Test
void testSaleByAgeForChildren() {//儿童半折
when(mockPassenger.getAge()).thenReturn(10);
ticket.saleByAge(mockPassenger.getAge());//调用方法
assertEquals(50,ticket.getPrice());
}
测试类
package fit5171.monash.edu;
public class Ticket
{
private int ticket_id;
private int price;
Flight flight;
private boolean classVip; //indicates if this is bussiness class ticket or not
private boolean status; //indicates status of ticket: if it is bought by someone or not
Passenger passenger;
public Ticket(int ticket_id,int price, Flight flight, boolean classVip, Passenger passenger)
{
this.ticket_id=ticket_id;
this.price = price;
this.flight = flight;
this.classVip = classVip;
this.status = false;
this.passenger=passenger;
}
public Ticket() {
}
public int getTicket_id() {
return ticket_id;
}
public void setTicket_id(int ticket_id) {
this.ticket_id = ticket_id;
}
public int getPrice() { return price; }
public void setPrice(int price)
{
this.price = price;
saleByAge(passenger.getAge()); //changes price of the ticket according to the age category of passenger
serviceTax( ); //changes price by adding service tax to the ticket
}
public void saleByAge(int age)
{
int price = getPrice();
if(age < 15)
{
price-=(int)price*0.5;//50% sale for children under 15
this.price=price;
} else if(age>=60){
this.price=0; //100% sale for elder people
}
}
public Flight getFlight() {
return flight;
}
public void setFlight(Flight flight) {
this.flight = flight;
}
public boolean getClassVip() {
return classVip;
}
public void setClassVip(boolean classVip) {
this.classVip = classVip;
}
public boolean ticketStatus()
{
return status;
}
public void setTicketStatus(boolean status)
{
this.status = status;
}
public void serviceTax(){
this.price *= 1.12;
} //12% service tax
public Passenger getPassenger() {
return passenger;
}
public void setPassenger(Passenger passenger) {
this.passenger = passenger;
}
public String toString()
{
return"Ticket{" +'\n'+
"Price=" + getPrice() + "KZT, " + '\n' +
getFlight() +'\n'+ "Vip status=" + getClassVip() + '\n' +
getPassenger()+'\n'+ "Ticket was purchased=" + ticketStatus() + "\n}";
}
}
测试代码
package fit5171.monash.edu;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
class TicketTest {
private Ticket ticket;
private Passenger mockPassenger;
@BeforeEach
void setUp() {
// 初始化 Mock 对象
mockPassenger = mock(Passenger.class);
ticket = new Ticket(1, 100, null, false, mockPassenger); // 初始化 Ticket 对象
}
@Test
void testSaleByAgeForChildren() {
// 模拟乘客年龄为 10 岁
when(mockPassenger.getAge()).thenReturn(10);
// 调用方法
ticket.saleByAge(mockPassenger.getAge());
// 验证价格是否正确应用 50% 折扣
assertEquals(50, ticket.getPrice(), "Price should be 50 for children under 15.");
}
@Test
void testSaleByAgeForElderly() {
// 模拟乘客年龄为 65 岁
when(mockPassenger.getAge()).thenReturn(65);
// 调用方法
ticket.saleByAge(mockPassenger.getAge());
// 验证价格是否正确设置为 0
assertEquals(0, ticket.getPrice(), "Price should be 0 for elderly people aged 60 or above.");
}
@Test
void testSaleByAgeForAdults() {
// 模拟乘客年龄为 30 岁
when(mockPassenger.getAge()).thenReturn(30);
// 调用方法
ticket.saleByAge(mockPassenger.getAge());
// 验证价格是否保持不变
assertEquals(100, ticket.getPrice(), "Price should remain 100 for adults aged 15 to 59.");
}
@Test
void testSaleByAgeWithZeroPrice() {
// 模拟乘客年龄为 10 岁,并将初始价格设置为 0
ticket.setPrice(0);
when(mockPassenger.getAge()).thenReturn(10);
// 调用方法
ticket.saleByAge(mockPassenger.getAge());
// 验证价格是否保持为 0
assertEquals(0, ticket.getPrice(), "Price should remain 0 if original price is 0.");
}
}
-
-
- mock对象是不能实现具体的业务逻辑
-
package fit5171.monash.edu;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
class SaleByAgeTest {
private Ticket ticket;
private Flight flight;
private Passenger passenger;
@BeforeEach
void setUp() {
// ticket=new Ticket(1,100, flight, false, passenger);
// ticket=mock(Ticket.class);
}
@Test
void testSaleByAgeForChildren() {
// when(ticket.getPrice()).thenReturn(100);
// System.out.print(ticket.getPrice());
ticket.saleByAge(10);//这样子不会调用saleByage函数,因为这是mock对象,是空实现
verify(ticket).saleByAge(10);//验证saleByAge方法是否被调用,若未被调用,则报错
// doNothing().when(ticket).saleByAge(10); // 配置 saleByAge 方法的行为
// // 调用方法
// ticket.saleByAge(10);
// // 验证其他逻辑(如果有)
// assertEquals(50, ticket.getPrice());//事实上,不可能走saleByAge的业务逻辑,因为是mock对象
//--------------------------------------------------------------------------------
Ticket ticket = spy(new Ticket());
ticket.setPrice(100);
// 调用方法
ticket.saleByAge(10); // 调用实际逻辑
// 验证逻辑
assertEquals(50, ticket.getPrice()); // 验证价格是否正确
}
}
-
-
- 怎么使用mock实现业务逻辑,从而实现某个类的具体方法的单元测试
-
目标:A类依赖其他类,则把其他类给mock,然后A类需要真实对象。这样就可以测试A类中的方法。
举例:Ticket类需要调用Flight类和Passenger类,需要测试Ticket类中的saleByAge()方法。我们只需mock 一下Flight类和Passenger类 ,实例化对象 Ticket类,并按照Ticket类的构造方法Ticket()传参。这样我们即使没有Flight类和Passenger类的代码,也可以测试Ticket类的方法。 .
被测试类
package fit5171.monash.edu;
public class Ticket
{
private int ticket_id;
private int price;
Flight flight;
private boolean classVip; //indicates if this is bussiness class ticket or not
private boolean status; //indicates status of ticket: if it is bought by someone or not
Passenger passenger;
public Ticket(int ticket_id,int price, Flight flight, boolean classVip, Passenger passenger)
{
this.ticket_id=ticket_id;
this.price = price;
this.flight = flight;
this.classVip = classVip;
this.status = false;
this.passenger=passenger;
}
public Ticket() {
}
public int getTicket_id() {
return ticket_id;
}
public void setTicket_id(int ticket_id) {
this.ticket_id = ticket_id;
}
public int getPrice() { return price; }
public void setPrice(int price)
{
this.price = price;
saleByAge(passenger.getAge()); //changes price of the ticket according to the age category of passenger
serviceTax( ); //changes price by adding service tax to the ticket
}
public void saleByAge(int age)
{
int price = getPrice();
if(age < 15)
{
price-=(int)price*0.5;//50% sale for children under 15
this.price=price;
} else if(age>=60){
this.price=0; //100% sale for elder people
}
}
public Flight getFlight() {
return flight;
}
public void setFlight(Flight flight) {
this.flight = flight;
}
public boolean getClassVip() {
return classVip;
}
public void setClassVip(boolean classVip) {
this.classVip = classVip;
}
public boolean ticketStatus()
{
return status;
}
public void setTicketStatus(boolean status)
{
this.status = status;
}
public void serviceTax(){
this.price *= 1.12;
} //12% service tax
public Passenger getPassenger() {
return passenger;
}
public void setPassenger(Passenger passenger) {
this.passenger = passenger;
}
public String toString()
{
return"Ticket{" +'\n'+
"Price=" + getPrice() + "KZT, " + '\n' +
getFlight() +'\n'+ "Vip status=" + getClassVip() + '\n' +
getPassenger()+'\n'+ "Ticket was purchased=" + ticketStatus() + "\n}";
}
}
测试代码
package fit5171.monash.edu;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
class SaleByAgeTest {
private Ticket ticket;
private Flight mockFlight;
private Passenger mockPassenger;
@BeforeEach
void setUp() {
mockFlight=mock(Flight.class);
mockPassenger=mock(Passenger.class);
ticket=new Ticket(1,100, mockFlight, false, mockPassenger);
}
@Test
void testSaleByAgeForChildren() {//儿童半折
ticket.saleByAge(10);//调用方法
// System.out.print(ticket.getPrice());//获取价格
assertEquals(50,ticket.getPrice());
}
@Test
void testSaleByAgeForelder() {//老年人免费
ticket.saleByAge(70);//调用方法
// System.out.print(ticket.getPrice());//获取价格
assertEquals(0,ticket.getPrice());
}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.kler.cn/a/593176.html 如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!