当前位置: 首页 > article >正文

maven项目进行单元测试详细教程

      1. 为什么使用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);

      1. 新建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 项目的核心配置文件。
      1.  运行项目
  •  src/main/java 中创建一个简单的 Java 类,并编写 main 方法。
  • 右键点击类文件,选择 Run 来运行程序。
      1.  管理依赖
  • 如果需要添加依赖,可以在 pom.xml 文件的 <dependencies> 标签中添加依赖项,IDEA 会自动下载并管理这些依赖。
      1.  找不到类junit

删除C:\Users\<你的用户名>\.m2\repository\org\junit\junit 文件夹,maven-->clean一下

      1.  单元测试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,结果

      1.  生成测试用例的快捷键

CTRL+shift+t

      1.  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.");
    }
    
}

      1.  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());  // 验证价格是否正确
    }

}

      1.   怎么使用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());
    }
}

原文地址:https://blog.csdn.net/XG_17_38241417116/article/details/146362659
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.kler.cn/a/593176.html

相关文章:

  • 【论文阅读】Explainable Early Stopping for Action Unit Recognition
  • 在linux系统中运行window应用,并使用系统显卡能力的实现方案
  • 数据结构之链表(单链表)
  • 函数的介绍
  • QtitanRibbon在医疗场景中的精细化功能应用
  • ollama不安装到c盘,安装到其他盘
  • (2025|ICLR|华南理工,任务对齐,缓解灾难性遗忘,底层模型冻结和训练早停)语言模型持续学习中的虚假遗忘
  • 免费实用工具,wps/office/永中通吃!
  • oracle 基础知识事务的特性
  • Tomcat 与 Java 环境变量配置简明教程
  • PHP序列化漏洞
  • Python散点图(Scatter Plot):高阶分析、散点图矩阵、三维散点图及综合应用
  • 信息检索 information retrieval--lab练习(更新中)
  • Linux信号的处理
  • 【蓝桥杯速成】| 7.01背包练习生
  • 第5章:Docker镜像管理实战:构建、推送与版本控制
  • 【人工智能-前端OpenWebUI】--图片显示
  • 详细介绍GetDlgItem()
  • 器材借用管理系统详细设计基于Spring Boot-SSM
  • 汽车电子硬件架构 --- 车用电子芯片与处理器架构的技术演进及核心价值