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

为何标注@BeforeAll的setup方法未将ShippingAddress对象存入数据库?

问题分析与解决方案

可能的触发原因

  1. 事务未实际提交:@Rollback注解依赖@Transactional才能生效,你的setup方法仅添加了@Rollback(false)但未声明事务,导致save操作的事务默认被回滚,数据根本没写入数据库。
  2. 实体ID策略冲突:如果ShippingAddress实体的ID使用自动生成策略(比如@GeneratedValue(strategy = GenerationType.IDENTITY)),手动设置的ID"1"不会被数据库认可,实际生成的ID可能不是"1",测试时自然找不到对应数据。
  3. H2内存数据库特性:若使用内存模式的H2数据库,事务未提交的情况下,测试方法启动时数据库会回到初始状态,之前插入的数据不存在。

具体修正步骤

1. 给setup方法补全事务注解

确保数据能真正提交到数据库:

@BeforeAll
@Transactional
@Rollback(value = false)
public void setup() {
    testShippingAddress = shippingAddressRepository.save(new ShippingAddress("1","0722123443","Popescu","Ana","aleea lalelelor", "Romania","Sv","2112",null));
    System.out.println("保存后的收货地址ID:" + testShippingAddress.getId()); // 打印确认ID是否匹配预期
    testBillingAddress = billingAddressRepository.save(new BillingAddress("1", "0722123443","Popescu","Ana","aleea lalelelor", "Romania","Sv","2112",null));
}

2. 检查实体ID配置

打开ShippingAddress实体类,确认ID注解是否允许手动赋值:

@Entity
public class ShippingAddress {
    @Id
    // 若需要手动指定ID,不要添加@GeneratedValue注解,或设置策略为ASSIGN
    private String id;
    // 其他字段...
}

如果必须使用自动生成策略,不要手动设置ID,改用save返回对象的实际ID:

// setup方法中不手动设置ID
testShippingAddress = shippingAddressRepository.save(new ShippingAddress(null,"0722123443","Popescu","Ana","aleea lalelelor", "Romania","Sv","2112",null));
// 测试时使用生成后的真实ID
MvcResult mvcResult = mockMvc.perform(createPostRequest(OrdersController.PATH, 
    new CreateOrderReqDTO(OrderStatus.PAID, 3, 100.0, 100.0, 5.0, 
        testShippingAddress.getId(), testBillingAddress.getId(), "1", "1")))
    .andReturn();

3. 确认H2数据库配置

保证application.yml中的H2配置能保留内存数据:

spring:
  datasource:
    url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
    driver-class-name: org.h2.Driver
    username: sa
    password:

DB_CLOSE_DELAY=-1可以防止内存数据库在连接关闭时清空数据。

完整修正后的测试类示例

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = {OrdersApiApplication.class, H2JpaConfig.class})
@AutoConfigureMockMvc
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestClassOrder(ClassOrderer.OrderAnnotation.class)
@TestPropertySource("classpath:application.yml")
class OrdersControllerTest extends GenericIntegrationTest {

    @Autowired
    private MockMvc mockMvc;
    @Autowired
    private ShippingAddressRepository shippingAddressRepository;
    @Autowired
    private BillingAddressRepository billingAddressRepository;
    private static ShippingAddress testShippingAddress;
    private static BillingAddress testBillingAddress;

    @BeforeAll
    @Transactional
    @Rollback(value = false)
    public void setup() {
        // 若实体允许手动设置ID,直接使用指定值
        testShippingAddress = shippingAddressRepository.save(new ShippingAddress("1","0722123443","Popescu","Ana","aleea lalelelor", "Romania","Sv","2112",null));
        System.out.println("保存后的收货地址:" + testShippingAddress);
        testBillingAddress = billingAddressRepository.save(new BillingAddress("1", "0722123443","Popescu","Ana","aleea lalelelor", "Romania","Sv","2112",null));
    }

    @Nested
    class CreateOrderTests {

        @Nested
        class CreateProductTests {
            private ObjectMapper mapper = new ObjectMapper();

            @Test
            void shouldCreateOrderSuccessfully() throws Exception {
                // 若实体ID是自动生成,使用testShippingAddress.getId()而非硬编码"1"
                MvcResult mvcResult = mockMvc
                        .perform(createPostRequest(OrdersController.PATH, 
                            new CreateOrderReqDTO(OrderStatus.PAID, 3, 100.0, 100.0, 5.0, 
                                testShippingAddress.getId(), testBillingAddress.getId(), "1", "1")))
                        .andReturn();

                OrderDTO response = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() {
                });

                assertEquals(100.0, response.getTotal());
                assertEquals(100.0, response.getGrandTotal());
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:30:53