2015-11-24 88 views
2

我有Spring Boot項目,測試不失敗(但應該)。春季開機測試:測試通過,但不應該(假陽性)

我做錯了什麼或它是一個問題與春季?

對於一個小例子,我創建了一個包含2個實體(用戶和類別)和一個具有DELETE方法(https://github.com/sk8ter/demo)的控制器類的小項目。

類別實體擁有User實體的無級聯選擇一個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("https://stackoverflow.com/users/1")) 
       .andExpect(status().isOk()); 

//  EntityManagerFactory entityManagerFactory = context.getBean(EntityManagerFactory.class); 
//  SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class); 
//  sessionFactory.getCurrentSession().flush(); 
    } 
} 

如果我從DemoApplicationTests刪除@Transactional註釋,但在這種情況下,更改將提交給數據庫。

在測試中評論3行也沒有幫助。

+0

工作,你確定你有類別中,外國關鍵點給你的用戶? –

+0

是的,我還能如何區分特定用戶的類別。 –

+0

你應該有一個ManyToMany表(category_id,user_id),否則你將不得不爲不同的用戶重複相同的類別,但這不是線索,我問你是否確定你的db已經創建了類實體女巫被分配給某些用戶?因爲如果你這樣做,數據庫不會允許你刪除沒有在表上設置級聯選項的用戶,否則如果你只是刪除了一個用戶而沒有分配給類別,那麼測試會通過,因爲你沒有濫用外鍵規則 –

回答

2

我不想註釋方法或類@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("https://stackoverflow.com/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(); 
+0

解決方法似乎沒問題,但SessionFactory不起作用,因爲您使用JPA將它包裝在實體管理器中,您應該重寫您的測試,因爲您實際上正在檢查狀態是否正常,並且它在200之後使您.flush()會引起異常 –

+0

你有什麼建議?你能舉個例子嗎? –