为什么删除在应用程序中有效,但在测试中无效?

时间:2019-06-21 10:21:04

标签: java testing spring-data-jpa mockmvc

这是我的情况。

  

Category.java

@Getter
@Entity
@NoArgsConstructor
public class Category {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long id;
  private String name;

  @ManyToOne
  @JoinColumn(name = "masterCategory.id")
  private MasterCategory masterCategory;

  @OneToMany(mappedBy = "category", cascade = CascadeType.ALL, orphanRemoval = true)
  private List<Expense> expenses = new ArrayList<>();

}
  

Expense.java

@Getter
@Entity
@NoArgsConstructor
public class Expense {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long id;
  private BigDecimal amount;
  private String itemName;
  private LocalDateTime expenseDate;
  private String shopName;
  private boolean isIncome;

  @ManyToOne
  @JoinColumn(name = "shop.id")
  private Shop shop;

  @ManyToOne
  @JoinColumn(name = "bankingAccount.id")
  private BankingAccount bankingAccount;

  @ManyToOne
  @JoinColumn(name="category.id")
  private Category category;

  @ManyToOne
  @JoinColumn(name = "userAccount.id")
  private UserAccount userAccount;

  @ManyToOne
  @JoinColumn(name = "userGroup.id")
  private UserGroup userGroup;

}

我们可以看到,它们通过关系链接在一起。 对于每个此类,我还具有简单的服务,存储库和控制器(春季启动)。 CategoryService包含用于删除控制器的方法。它也很简单。

Category category = categoryRepository.selectCategory(getLoggedUsername(),groupId,masterCatId,categoryId);
categoryRepository.delete(category);
return categoryConverter.toMinimalDto(category);

当我运行该应用程序时,一切正常,将其从数据库中删除类别,并删除与该类别相关的费用。 有一天,我决定编写测试,因为我厌倦了手动检查所有内容。这是测试方法:

@Test
@WithMockUser(username = LOGIN)
public void shouldDeleteCategoryAndConnectedExpenses__andReturn200() throws Exception {
    //given
    mvc.perform(get("/api/budget/1/master/1"))
            .andExpect(status().isOk())
            .andExpect(content().json(testUtil.openJson("categories/categoriesFromSelectedBudget.json")));
    mvc.perform(get("/api/budget/1/master/1/category/1/expense"))
            .andExpect(status().isOk())
            .andExpect(content().json(testUtil.openJson("expenses/expensesFromCategory1.json")));
    //when
    mvc.perform(delete("/api/budget/1/master/1/category/1"))
            .andExpect(status().isOk());
    //then
    mvc.perform(get("/api/budget/1/master/1"))
            .andExpect(status().isOk())
            .andExpect(content().json(testUtil.openJson("categories/categoriesAfterDelete.json")));
    mvc.perform(get("/api/budget/1/master/1/category/1/expense"))
            .andExpect(status().isNotFound());
}

我有一个特殊的postgresDB用于测试,在这里我检查delete是否确实在做它的工作。我通过检查响应json是否是我想要的JSON来实现。简单的东西。

  • 第一个get(categoriesFromSelectedBudget.json)包含3个元素
  • 第三get(categoriesAfterDelete.json)包含2个元素。

这些json是100%正确的。

问题是:为什么运行应用程序时一切正常(我可以看到带有delete的SQL,从数据库中删除了正确的行),但是运行测试时却引发了以下异常:

  

java.lang.AssertionError:[]:期望2个值但得到3个

在测试中,delete给了我http 200,但显然不是删除该元素。也没有带删除的SQL。为什么?我做错了什么?

1 个答案:

答案 0 :(得分:0)

感谢潜在客户。经过一些调试之后,我意识到测试的行为是这样的,因为测试类顶部有@Transactional。我这样做是为了在每种方法后刷新数据库。我将其替换为@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD),一切似乎都正常运行。