Spring Boot抽象类子类AirportService的单元测试实现方案
单元测试实现方案
是否需要测试getFileName()?
需要。虽然这个方法仅返回固定字符串,但它是readFromCsv()读取文件的核心依赖项,若文件名指定错误会直接触发文件找不到的异常。测试它能快速验证子类是否正确绑定了目标CSV文件,避免集成阶段才暴露问题。
测试getFileName()
getFileName()是protected方法,若测试类与AirportService在同一包下,可直接调用;若不在同包,通过反射访问即可。
同包测试示例(JUnit 5)
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; class AirportServiceTest { private final AirportService airportService = new AirportService(); @Test void getFileName_ShouldReturnCorrectFileName() { String fileName = airportService.getFileName(); assertEquals("airport.csv", fileName); } }
跨包反射测试示例
import org.junit.jupiter.api.Test; import java.lang.reflect.Method; import static org.junit.jupiter.api.Assertions.assertEquals; class AirportServiceTest { private final AirportService airportService = new AirportService(); @Test void getFileName_ShouldReturnCorrectFileName() throws Exception { Method method = AirportService.class.getDeclaredMethod("getFileName"); method.setAccessible(true); String fileName = (String) method.invoke(airportService); assertEquals("airport.csv", fileName); } }
测试getData()
getData()的核心逻辑是遍历CsvToBean实例、处理每个AirportBean并返回结果列表。我们可以用Mockito模拟CsvToBean对象,构造测试数据验证处理逻辑是否符合预期。
测试示例(JUnit 5 + Mockito)
import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.junit.jupiter.api.extension.ExtendWith; import com.opencsv.bean.CsvToBean; import java.util.List; import static org.mockito.Mockito.*; import static org.junit.jupiter.api.Assertions.*; @ExtendWith(MockitoExtension.class) class AirportServiceTest { private final AirportService airportService = new AirportService(); @Mock private CsvToBean<AirportBean> mockCsvToBean; @Test void getData_ShouldProcessAndReturnAirportBeans() { // 构造模拟业务数据 AirportBean mockBean1 = new AirportBean(); mockBean1.setCode("ABC"); mockBean1.setName("测试机场1"); AirportBean mockBean2 = new AirportBean(); mockBean2.setCode("DEF"); mockBean2.setName("测试机场2"); // 配置mock对象的迭代器返回模拟数据 when(mockCsvToBean.iterator()).thenReturn(List.of(mockBean1, mockBean2).iterator()); // 调用目标方法 List<AirportBean> result = airportService.getData(mockCsvToBean); // 验证结果正确性 assertEquals(2, result.size()); assertEquals("ABC", result.get(0).getCode()); assertEquals("测试机场2", result.get(1).getName()); // 验证mock对象的方法调用次数 verify(mockCsvToBean, times(1)).iterator(); } }
注意事项
- 如果
getData()包含特定业务逻辑(如字段转换、数据过滤),需构造对应测试场景(例如不符合过滤条件的Bean),验证逻辑是否生效。 - 确保
AirportBean的getter/setter方法正常工作,避免因Bean自身问题导致测试失败。
额外:全流程验证(可选)
若想覆盖完整的CSV读取链路,可在test/resources目录下放置测试用的airport.csv文件,直接调用readFromCsv()验证返回数据与测试文件内容一致,这样能同时验证getFileName()和文件读取逻辑:
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; class AirportServiceTest { private final AirportService airportService = new AirportService(); @Test void readFromCsv_ShouldReturnCorrectDataFromTestFile() { List<AirportBean> result = airportService.readFromCsv(AirportBean.class, null); // 根据测试文件内容断言,示例假设文件有2条数据 assertEquals(2, result.size()); assertEquals("JFK", result.get(0).getCode()); } }
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

