簡體   English   中英

嘗試集成測試 spring-data-jpa 拋出 MockMVC,但更新不起作用

[英]Try integration test spring-data-jpa throw MockMVC, but update does not work

我使用 spring-data-jpa 和 spring-boot-web 構建了一個演示應用程序。 我嘗試使用 MockMVC 構建集成測試,它將調用添加接口,然后是修改接口,最后是查詢接口,並確定更改是否生效。 我還使用“spring.jpa.properties.hibernate.show_sql”屬性,打印 sql 登錄控制台。 但是,在控制台中,我只看到了一個insert sql,一個query sql,沒有看到update sql。另外,我使用的@PreUpdate 注解沒有生效,因為覆蓋率檢查顯示沒有執行。

但是當我通過 postman 測試時,一切都非常正常並且符合預期:我看到更新 sql 並且它也執行了@PreUpdate。

編寫測試用例時我做錯了什么?

這是我的測試代碼。 Rest Api 只是調用JpaRepository。

@ExtendWith(SpringExtension.class)
@AutoConfigureMockMvc(addFilters = false)
@SpringBootTest
@Transactional
class TechyoControllerTest {
    @Autowired
    private MockMvc mockMvc;
    @Autowired
    private ObjectMapper objectMapper;

    @SneakyThrows
    @Test
    public void should_update_success() {
        String createRequest = "{\"name\":\"name_test\",\"money\":12.3}";
        MvcResult mvcCreateResult = mockMvc
                .perform(MockMvcRequestBuilders.post("/accountItems")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(createRequest))
                .andReturn();
        AccountItemResponse createResult =
                objectMapper.readValue(mvcCreateResult.getResponse().getContentAsString(), AccountItemResponse.class);

        // update
        String updateRequest = "{" +
                "  \"name\": \"updated_name\"," +
                "  \"date\": " + createResult.getTransactionTime().getTime() + "," +
                "  \"lines\": [{" +
                "    \"name\": \"line1\"," +
                "    \"money\": 12" +
                "  }, {\n" +
                "    \"name\": \"line1\"," +
                "    \"money\": 12" +
                "  }, {\n" +
                "    \"name\": \"line1\"," +
                "    \"money\": -12" +
                "  }]" +
                "}";
        MvcResult mvcUpdateResult = mockMvc
                .perform(MockMvcRequestBuilders.put("/accountItems/" + createResult.getId())
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(updateRequest))
                .andExpect(status().isOk())
                .andReturn();
        AccountItemResponse updateResult
                = objectMapper.readValue(mvcUpdateResult.getResponse().getContentAsString(), AccountItemResponse.class);
        assertThat(updateResult.getId()).isEqualTo(createResult.getId());
        assertThat(updateResult.getTransactionTime()).hasSameTimeAs(createResult.getTransactionTime());
        assertThat(updateResult.getTotal()).isEqualTo(new BigDecimal("12.00"));
        assertThat(updateResult.getAccountItemLines()).hasSize(3);

        // query
        MvcResult mvcGetResult = mockMvc
                .perform(MockMvcRequestBuilders.get("/accountItems/" + createResult.getId()))
                .andExpect(status().isOk())
                .andReturn();
        AccountItemResponse getResult
                = objectMapper.readValue(mvcGetResult.getResponse().getContentAsString(), AccountItemResponse.class);
        assertThat(getResult.getId()).isEqualTo(createResult.getId());
        assertThat(getResult.getTransactionTime()).hasSameTimeAs(createResult.getTransactionTime());
        assertThat(getResult.getTotal()).isEqualTo(new BigDecimal("12.00"));
        assertThat(getResult.getAccountItemLines()).hasSize(3);
    }
}

這是我的實體代碼

@MappedSuperclass
@Getter
@Setter
@RequiredArgsConstructor
@Accessors(chain = true)
public class BasePO {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(updatable = false, nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date createTime;
    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date updateTime;

    @PrePersist
    protected void prePersist() {
        Date now = new Date();
        if (createTime == null) {
            createTime = now;
        }
        if (updateTime == null) {
            updateTime = now;
        }
    }

    @PreUpdate
    protected void preUpdate() {
        updateTime = new Date();
    }

    @PreRemove
    protected void preRemove() {
        updateTime = new Date();
    }
}
@Entity
@Table(name = "account_item")
@Accessors(chain = true)
@Getter
@Setter
@RequiredArgsConstructor
public class AccountItemPO extends BasePO {
    @Column(nullable = false)
    private String name;
    @Column(nullable = false, columnDefinition = "decimal(10,2)")
    private BigDecimal totalMoney;
    private Date transactionTime;
}

這個集成測試本身並沒有拋出任何異常(因為我返回的數據不包含updateTime等字段)。 程序執行加斷點顯示確實更新了數據,但是create_time/update_time設置為null(雖然我用的是nullable = false)

這是從控制台打印的 sql

Hibernate: 
    insert 
    into
        account_item
        (create_time, update_time, name, total_money, transaction_time) 
    values
        (?, ?, ?, ?, ?)

Hibernate: 
    select
        count(*) as col_0_0_ 
    from
        account_item accountite0_ 
    where
        accountite0_.id=?

也許你可以試試這個解決方案。 它適用於 Spring Boot 2.7.5(包括 GraphQL)

https://github.com/graphql-java/graphql-java-spring/issues/30#issuecomment-860026650

Handler:
         Type = org.springframework.boot.autoconfigure.graphql.servlet.GraphQlWebMvcAutoConfiguration$$Lambda$1547/1627578183 Async:
Async started = true
 Async result = org.springframework.web.servlet.function.DefaultEntityResponseBuilder$DefaultEntityResponse@3ec151c5

不知何故,我看到日志說 async = true。 所以我認為關鍵是等待異步完成

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM