3

失敗しないテストを含むSpring Bootプロジェクトがあります(ただし、失敗するはずです)。

私は何か間違ったことをしていますか、それともSpringの問題ですか?

小さな例として、2 つのエンティティ (ユーザーとカテゴリ) と DELETE メソッドを持つ 1 つのコントローラー クラス ( https://github.com/sk8ter/demo )を持つ小さなプロジェクトを作成しました。

カテゴリ エンティティには、カスケードオプションのないユーザー エンティティの 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アノテーションを削除すると、テストは失敗しますが、この場合、変更は DB にコミットされます。

テストでコメントされた 3 行も役に立ちません。

4

1 に答える 1

3

すべてのテストをべき等にしたかったので、@Rollback(false)でメソッドまたはクラスに注釈を付けたくありませんでした。@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 ドキュメントからは機能しません

// Manual flush is required to avoid false positive in test
sessionFactory.getCurrentSession().flush();
于 2015-11-25T14:25:52.247 に答える