Java Lambda表达式单元测试覆盖率问题:内部逻辑未被覆盖
问题描述
你需要为下面的getSessionBuilderConfigurer方法编写单元测试,覆盖其中Lambda表达式的内部逻辑,但当前的测试仅验证了方法返回非空,完全没覆盖Lambda里的逻辑:
原方法代码:
protected SessionBuilderConfigurer getSessionBuilderConfigurer() { return cqlSessionBuilder -> { ProgrammaticDriverConfigLoaderBuilder programmaticDriverConfigLoaderBuilder; programmaticDriverConfigLoaderBuilder = getCassandraWithoutSslConfiguration();//Local method DriverConfigLoader driverConfigLoader = programmaticDriverConfigLoaderBuilder.build(); return cqlSessionBuilder .withConfigLoader(driverConfigLoader) .withAuthCredentials(properties.getUsername(), properties.getPassword()); }; }
当前测试代码:
//Class level @ExtendWith(MockitoExtension.class) @InjectMocks WaausCassandraConfiguration configuration; //Inside method Assertions.assertNotNull(configuration.getSessionBuilderConfigurer());
解决方案
要覆盖Lambda内部逻辑,核心是调用Lambda表达式并验证其执行过程,具体步骤如下:
1. 准备测试依赖与Mock对象
需要Mock以下核心依赖:
- 目标类的
properties属性(用于提供用户名密码) getCassandraWithoutSslConfiguration()方法返回的ProgrammaticDriverConfigLoaderBuilderDriverConfigLoader实例CqlSessionBuilder实例(Lambda的入参)
同时使用@Spy替代单独的@InjectMocks,这样可以部分Mock目标类的protected方法。
2. 编写完整测试用例
@ExtendWith(MockitoExtension.class) class WaausCassandraConfigurationTest { // 使用@Spy+@InjectMocks,既注入依赖又能mock类内的protected方法 @Spy @InjectMocks private WaausCassandraConfiguration configuration; // Mock配置属性类(根据实际类名调整) @Mock private CassandraProperties properties; // Mock配置构建器 @Mock private ProgrammaticDriverConfigLoaderBuilder mockConfigLoaderBuilder; // Mock加载器实例 @Mock private DriverConfigLoader mockDriverConfigLoader; // Mock会话构建器(Lambda的入参) @Mock private CqlSessionBuilder mockCqlSessionBuilder; @Test void getSessionBuilderConfigurer_shouldApplyConfigAndAuthCredentials() { // 1. 设置测试数据 String testUsername = "test_user"; String testPassword = "test_pass"; when(properties.getUsername()).thenReturn(testUsername); when(properties.getPassword()).thenReturn(testPassword); // 2. Mock protected方法的返回值 doReturn(mockConfigLoaderBuilder).when(configuration).getCassandraWithoutSslConfiguration(); when(mockConfigLoaderBuilder.build()).thenReturn(mockDriverConfigLoader); // 3. Mock链式调用的返回值(因为Lambda里是链式调用,需保证每个方法返回自身mock) when(mockCqlSessionBuilder.withConfigLoader(mockDriverConfigLoader)).thenReturn(mockCqlSessionBuilder); when(mockCqlSessionBuilder.withAuthCredentials(testUsername, testPassword)).thenReturn(mockCqlSessionBuilder); // 4. 获取Configurer并执行Lambda逻辑 SessionBuilderConfigurer configurer = configuration.getSessionBuilderConfigurer(); // 调用Configurer的核心方法(根据SessionBuilderConfigurer的函数式接口方法名调整,比如configure/apply) configurer.configure(mockCqlSessionBuilder); // 5. 验证所有预期逻辑都被执行 verify(configuration).getCassandraWithoutSslConfiguration(); verify(mockConfigLoaderBuilder).build(); verify(mockCqlSessionBuilder).withConfigLoader(mockDriverConfigLoader); verify(mockCqlSessionBuilder).withAuthCredentials(testUsername, testPassword); } }
关键说明
- @Spy的作用:允许我们mock目标类中的特定方法(比如
getCassandraWithoutSslConfiguration()),同时保留其他方法的真实逻辑,避免依赖真实的配置构建流程。 - 链式调用Mock:因为Lambda中对
CqlSessionBuilder使用了链式调用,必须确保每个方法调用都返回自身的mock对象,否则会抛出空指针异常。 - 执行Lambda:通过调用
SessionBuilderConfigurer的函数式方法(比如configure),触发Lambda内部逻辑执行,从而覆盖代码。 - 验证调用:通过
verify方法确认所有预期的方法都被正确调用,确保逻辑符合预期。
内容的提问来源于stack exchange,提问作者Mayur Gite
相关产品推荐
相关产品推荐

