Spring Boot中用Mockito编写Repository的JUnit测试遇空指针问题求助
解决Repository测试空指针及正确测试方案
现有代码的问题
- Mock未初始化:仅用
@Mock注解但未触发Mockito的初始化逻辑,导致repository实例为null。 - 类型错误:声明的
Repository是泛型父类,应该用具体的AddressRepo类型,否则无法调用getAdressResults()方法。 - 实体方法调用错误:实体类里的方法是
setId(),你写的setid(1))存在语法错误(多了闭合括号+方法名大小写错误)。
方案一:Mock测试(验证方法调用逻辑,无需真实数据库)
这种方式适合快速测试业务层对Repository的调用逻辑,不涉及真实SQL执行:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) // 初始化Mockito的Mock对象 public class AddressRepoMockTest { @Mock // 声明具体的AddressRepo类型 private AddressRepo addressRepo; @Test public void testGetAddressResults() { // 构造测试数据 Address address = new Address(); address.setId(1); // 修正方法名和语法 address.setLine1("address line 1"); List<Address> addressList = new ArrayList<>(); addressList.add(address); // Mock方法返回值 when(addressRepo.getAdressResults()).thenReturn(addressList); // 调用方法并断言 List<Address> addresses = addressRepo.getAdressResults(); assertThat(addresses.get(0).getLine1()).isEqualToIgnoringCase("address line 1"); } }
方案二:集成测试(验证SQL正确性,用真实测试数据库)
如果要验证@Query里的SQL是否正确执行,需要用集成测试,Spring提供了@DataJpaTest注解自动配置测试环境(默认用H2内存数据库):
1. 先修正Repository的泛型错误
你的AddressRepo继承JpaRepository时用了SourceAddress,但实体类是Address,这里明显是笔误,先修正:
@Repository public interface AddressRepo extends JpaRepository<Address, Integer>, JpaSpecificationExecutor<Address> { @Query(value = "select * from ADDRESS", nativeQuery = true) // 表名和实体类@Table一致,去掉多余空格 List<Address> getAdressResults(); }
2. 编写集成测试类
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @DataJpaTest // 自动配置JPA测试环境,创建内存数据库 public class AddressRepoIntegrationTest { @Autowired // 注入真实的AddressRepo代理实例 private AddressRepo addressRepo; @Test public void testGetAddressResults() { // 先往测试数据库插入数据 Address testAddress = new Address(); testAddress.setLine1("address line 1"); testAddress.setLine2("line 2"); addressRepo.save(testAddress); // 调用Repository方法 List<Address> addresses = addressRepo.getAdressResults(); // 断言结果 assertThat(addresses).isNotEmpty(); assertThat(addresses.get(0).getLine1()).isEqualToIgnoringCase("address line 1"); } }
内容的提问来源于stack exchange,提问作者unknown1101
相关产品推荐
相关产品推荐

