Spring boot test: Test passes, but should not (false positive)

若如初见. 提交于 2019-12-10 19:22:04

问题


I have Spring Boot project with test that does not fail (but should).

Am I doing something wrong or it is a issue with Spring?

For an small example I have created a small project with 2 entities (User and Category) and one Controller class that has DELETE method (https://github.com/sk8ter/demo).

Category entity has an id of User entity without cascade option, so it should fail while deleting a User that has category:

@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;
    ...
}

Controller is also is pretty simple:

@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);
    }
}

And finally a test:

@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();
    }
}

Test will fail in case I remove @Transactional annotation from DemoApplicationTests, but in this case changes will be committed to a DB.

Commented 3 lines in the test does not help either.


回答1:


I did not want to annotate method or class with @Rollback(false), since I wanted all my tests be idempotent. In case I annotate @Rollback(false), H2 also fails with foreign key's constraints.

I found a solution:

@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();
    }
}

Key lines:

@PersistenceContext
EntityManager em;
...
// Manual flush is required to avoid false positive in test
em.flush();

So SessionFactory does not work from Spring Documentation

// Manual flush is required to avoid false positive in test
sessionFactory.getCurrentSession().flush();


来源:https://stackoverflow.com/questions/33905773/spring-boot-test-test-passes-but-should-not-false-positive

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!