You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cucumber+SpringBoot+JPA测试中Repository返回Null问题求助

Cucumber测试中JPA Repository查询返回Null但数据库存在数据的排查方案

在Cucumber测试里调用JPA Repository的findCustomerShipmentByShipmentNumber方法返回Null,但确认数据库中存在对应数据,怀疑是数据库连接问题,以下是相关代码和实用排查步骤:


相关代码与配置

CucumberConfig.java

package com.xxx.xxx.cucumber;
import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan(basePackages = {
    "com.xxx.xxx.configuration"
})
@CucumberContextConfiguration
@SpringBootTest
public class CucumberConfig {
}

CucumberRunner.java

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;

@ContextConfiguration(classes = { CucumberConfig.class })
@RunWith(Cucumber.class)
@CucumberOptions(
  features = "src/test/resources/features",
  glue={"com.xxx.xxx.cucumber"},
  plugin = {
    "html:target/site/cucumber/cucumber-report.html",
    "junit:target/site/cucumber/cucumber-report.xml",
  })
@ActiveProfiles("cucumber")
public class CucumberRunner {
}

ShipmentBackEndValidationTestsIntegrationTest.java(部分)

@Component
public class ShipmentBackEndValidationIntegrationTest implements CucumberStateVariables { 
  private final RestTemplate restTemplate;
  private static final Logger LOGGER = LoggerFactory.getLogger(ShipmentBackEndValidationIntegrationTest.class);
  final CucumberUtil cucumberUtil;
  AppConfig appConfig;
  CustomerShipmentRepository customerShipmentRepository;

  @Autowired
  public ShipmentBackEndValidationIntegrationTest(
    AppConfig appConfig,
    CucumberUtil cucumberUtil,
    OceanRestTemplateHelper oceanRestTemplateHelper,
    CustomerShipmentRepository customerShipmentRepository
    )
    throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
    LOGGER.warn("SU: {}", appConfig.getSecurity().getSystemUser());
    LOGGER.warn("SUP: {}",appConfig.getSecurity().getSystemUserPassword());
    this.appConfig = appConfig;
    this.cucumberUtil = cucumberUtil;
    this.restTemplate = oceanRestTemplateHelper.buildRestTemplate(oceanRestTemplateHelper.lrdUserAuth());
    this.customerShipmentRepository = customerShipmentRepository;
  }
}

ShipmentBackEndValidationStepDefs.java

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.client.HttpClientErrorException;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static org.junit.Assert.*;

public class ShipmentBackEndValidationStepDefs extends ShipmentBackEndValidationIntegrationTest {

  private CustomerShipment requestShipment;
  private CustomerShipment ResponseShipment;
  private boolean expectException;
  private final List<RuntimeException> exceptions = new ArrayList<>();
  private static final Logger LOGGER = LoggerFactory.getLogger(CustomerShipmentApiStepDefs.class);
  private String errorMessage;

  public ShipmentBackEndValidationStepDefs(
    AppConfig appConfig,
    CucumberUtil cucumberUtil,
    OceanRestTemplateHelper oceanRestTemplateHelper,
    CustomerShipmentRepository customerShipmentRepository
    )
     throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
     super(appConfig, cucumberUtil, oceanRestTemplateHelper, customerShipmentRepository);
     this.customerShipmentRepository = customerShipmentRepository;
   }

  @Given("shipment for {string} branch")
  public void shipmentWithValidAndIncompleteDataInCarrierDetailsIsCreatedForStringBranch(String branchCode) throws IOException {
    this.clearExceptionList();
    TestDataSerializer.changeTimezoneContextToBranch(branchCode);
    requestShipment = TestDataSerializer.generateCustomerShipmentFromJson("shipments/CustomerShipment.json");
  }

  @When("the user clicks the save button")
  public void the_user_clicks_the_save_button() {
    try{  
      this.ResponseShipment = saveCustomerShipment(requestShipment);
      LOGGER.info(String.format("Successfully saved shipment number: ", this.ResponseShipment.getShipmentNumber()));
      System.out.println("Shipment saved successfully: "+ ResponseShipment.getShipmentNumber());
    } catch (HttpClientErrorException err) {
      this.errorMessage = err.getMessage();
    }
  }

  @Then("the data is saved to the database")
  public void dataIsSavedToDatabase1(){
    String shipmentNumber = ResponseShipment.getShipmentNumber();
   
    Optional<CustomerShipment> resultShipment = customerShipmentRepository.findCustomerShipmentByShipmentNumber(shipmentNumber);
    System.out.println("Print -- "+resultShipment);
    assertTrue(resultShipment.isPresent());
  }
}

CustomerShipmentRepository.java

package com.xxx.xxx.shipment.repositories;

import com.expd.ocean.base_repository.BaseRepository;
import com.expd.ocean.shipment.entities.CustomerShipment;
import jakarta.transaction.Transactional;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;
import java.util.UUID;

@Repository
public interface CustomerShipmentRepository extends JpaRepository<CustomerShipment, UUID>, BaseRepository {

  @EntityGraph(value = "CustomerShipment.fullCustomerShipment", type = EntityGraph.EntityGraphType.LOAD)
  Optional<CustomerShipment> findCustomerShipmentByShipmentNumber(String shipmentNumber);

}

排查步骤

  1. 确认测试环境数据库配置

    • 检查application-cucumber.properties/yml中的数据库URL、用户名、密码,确保和你手动查询的是同一个库(很多测试会用内存库或测试专用库,别查错环境)。
    • 在CucumberConfig中注入DataSource,打印dataSource.getConnection().getMetaData().getURL(),直接验证当前连接的数据库。
  2. 排查事务边界问题

    • 如果saveCustomerShipment是REST接口调用,服务端的事务可能在请求结束后才提交,测试代码中立刻查询会看不到数据。可以改成直接调用Service方法,或者在查询前短暂等待(仅用于验证)。
    • 若测试类加了@Transactional,默认会在测试结束后回滚数据,导致查询不到,可去掉该注解或手动提交事务。
  3. 修复Repository扫描问题

    • 当前CucumberConfig的@ComponentScan仅扫描com.xxx.xxx.configuration,但Repository在com.xxx.xxx.shipment.repositories,Spring无法扫描到。修改@ComponentScan加入Repository所在包,或添加@EnableJpaRepositories(basePackages = "com.xxx.xxx.shipment.repositories")。
    • 在步骤类构造方法中打印customerShipmentRepository,确认是否成功注入。
  4. 验证查询逻辑

    • 暂时去掉Repository方法上的@EntityGraph,用简单查询测试,排除EntityGraph配置错误导致的查询失败。
    • 打印shipmentNumber的具体值,和数据库中数据对比,检查大小写、空格等字符匹配问题(部分数据库字符集区分大小写)。
  5. 检查时区影响

    • 步骤中调用了changeTimezoneContextToBranch方法,若CustomerShipment包含时区相关字段,可能因时区不一致导致查询条件不匹配,可临时注释时区切换代码测试。

内容的提问来源于stack exchange,提问作者Silver555

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 21:34:57