Java 如何做单元测试

在日常的Java开发中,写好功能代码只是完成了一半,另一半是确保代码“不出错”。就像我们买了一台新咖啡机,装完还要测试它能不能正常出咖啡、会不会漏水,Java代码也需要通过“单元测试”来验证每个小模块都能按预期工作。很多新手开发者觉得单元测试是“额外工作”,其实它能帮我们提前揪出bug,还能在后续改代码时避免牵一发而动全身。

单元测试是什么?用买奶茶的例子秒懂

假设你开了一家奶茶店,做一杯珍珠奶茶需要“煮珍珠、冲茶汤、加牛奶、放珍珠”四个步骤。单元测试就像你对每个步骤单独检查:煮珍珠会不会煮糊?冲茶汤的浓度对不对?加牛奶的量够不够?放珍珠的数量有没有少?只要每个小步骤都合格,整杯奶茶才不会踩雷。

Java 如何做单元测试

放到Java里,单元测试就是针对代码里的“最小功能单元”(比如一个计算价格的方法、一个判断用户是否登录的函数)写测试代码,验证输入不同内容时,输出是否和预期一致。比如你写了一个计算奶茶总价的方法,输入“大杯、加珍珠、3杯”,应该算出“39元”,单元测试就是帮你确认这个计算结果不会错。

最常用的单元测试工具:JUnit,上手超简单

Java做单元测试最常用的工具是JUnit,就像奶茶店最常用的量杯、温度计,是行业标配。不用自己写复杂的测试框架,导入依赖就能用,新手也能快速上手。

举个实际的小例子:假设我们写了一个计算奶茶总价的Java方法,代码大概是这样的(不用纠结语法,重点看逻辑):

`java

public class MilkTeaCalculator {

// 计算总价:大杯基础20元,加珍珠5元,买3杯打9折

public static double calculatePrice(String size, boolean hasPearl, int count) {

double basePrice = "大杯".equals(size) ? 20 : 15;

double total = basePrice * count + (hasPearl ? 5 * count : 0);

return count >= 3 ? total * 0.9 : total;

}

}

`

现在我们要给这个方法写单元测试,只需要用JUnit写几行代码:

`java

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class MilkTeaCalculatorTest {

@Test // 标记这是一个测试方法

public void testLargePearlThreeCup() {

// 输入:大杯、加珍珠、3杯,预期总价39元

double result = MilkTeaCalculator.calculatePrice("大杯", true, 3);

assertEquals("大杯加珍珠3杯总价错误", 39.0, result, 0.01);

}

}

`

运行这个测试,如果输出的结果是39元,测试就通过;如果算成40元,测试会直接标红,告诉你哪里错了。整个过程就像你用秤称奶茶,重量不对立刻就能发现。

单元测试的核心原则:只测“小单元”,不依赖其他代码

很多新手写单元测试会踩一个坑:测试的时候连带着测了数据库、其他接口,结果一个环节出错,整个测试就失败,根本找不到问题在哪。就像你检查奶茶时,连带着查了冰箱的温度、收银员的系统,本来只是珍珠煮的时间不对,结果怪到冰箱上,太浪费时间。

正确的做法是“隔离测试”:如果一个方法需要调用数据库,就模拟出假的数据库数据,不用真的连数据库;如果需要用到其他模块,就把其他模块“藏起来”,只测当前这个小功能。比如刚才的奶茶价格计算方法,不用真的去拿门店的库存、当天的折扣,只测输入的参数和计算结果对不对,这样测试才快、才准。

单元测试的好处:帮你省掉80%的调试时间

很多人觉得写单元测试耽误时间,其实是捡了芝麻丢了西瓜。比如你写了一个会员积分的功能,上线后发现积分算错了,这时候再找bug,要翻几十行甚至几百行代码,还要改用户数据,可能花大半天;但如果提前写了单元测试,只需要运行测试,看哪一个测试用例标红,立刻就能找到积分计算的错误,几分钟就能修好。

而且后续改代码时,比如奶茶店调整了大杯的基础价,只要跑一遍单元测试,就能确认所有和价格相关的逻辑都没出错,不用怕改一个参数牵连出其他问题。

其实单元测试不难,核心就是“把每个小功能的预期结果写出来,让代码自己验证”,就像给每个奶茶步骤都加个小检查,确保每一杯都合格。

上一篇 TypeScript Omit 怎么用