我的Spring Boot项目测试没有失败(但应该)。
我做错了什么或者是Spring的问题?
对于一个小例子,我创建了一个包含2个实体(User和Category)的小项目和一个具有DELETE方法(https://github.com/sk8ter/demo)的Controller类。
类别实体的ID为不带级联选项的用户实体,因此删除具有类别的用户时会失败:
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue
private long id;
private String name;
...
}
@Entity
@Table(name = "category")
public class Category {
@Id
@GeneratedValue
private long id;
private String name;
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
...
}
控制器也非常简单:
@RestController
@RequestMapping(value = "/users", produces = "application/json;charset=UTF-8")
public class UserCategory {
@Autowired
private UserRepository userRepository;
@ResponseStatus(HttpStatus.OK)
@RequestMapping(value = "/{id}", method = DELETE, consumes = MediaType.ALL_VALUE)
public void deleteCategory(@PathVariable Long id) {
User user = userRepository.getOne(id);
userRepository.delete(user);
}
}
最后一个测试:
@Transactional
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = DemoApplication.class)
public class DemoApplicationTests {
@Autowired
protected WebApplicationContext context;
protected MockMvc mockMvc;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
@Test
public void testName() throws Exception {
mockMvc.perform(delete("/users/1"))
.andExpect(status().isOk());
// EntityManagerFactory entityManagerFactory = context.getBean(EntityManagerFactory.class);
// SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
// sessionFactory.getCurrentSession().flush();
}
}
如果我从 DemoApplicationTests 中删除 @Transactional 注释,测试将失败,但在这种情况下,更改将提交给数据库。
测试中评论的3行也无济于事。
答案 0 :(得分:3)
我不想用 @Rollback(false)注释方法或类,因为我希望我的所有测试都是idempotent。如果我注释 @Rollback(false),H2也会因外键的约束而失败。
我找到了解决方案:
@Transactional
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = DemoApplication.class)
public class DemoApplicationTests {
@Autowired
protected WebApplicationContext context;
protected MockMvc mockMvc;
@PersistenceContext
EntityManager em;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
@Test
public void testName() throws Exception {
mockMvc.perform(delete("/users/1"))
.andExpect(status().isOk());
em.flush();
}
}
关键行:
@PersistenceContext
EntityManager em;
...
// Manual flush is required to avoid false positive in test
em.flush();
因此,SessionFactory无法在Spring Documentation
中运行// Manual flush is required to avoid false positive in test
sessionFactory.getCurrentSession().flush();