Spring data mongodb 唯一索引(@Indexed)单元测试注意事项

wangxingg 2019-07-01

问题

Spring data mongodb Entity有一个字段设置了唯一索引

@Indexed(unique=true)
private String uid;

测试不能添加uid重复的记录

/**
     *  测试插入UID重复记录失败
     */
    MyCardDO myCardDO1 = new MyCardDO();
    myCardDO1.setUid("1");
    myCardService.add(myCardDO1);

    try {
        MyCardDO myCardDO2 = new MyCardDO();
        myCardDO2.setUid("1");
        myCardService.add(myCardDO2);

        Assert.fail();
    } catch (DuplicateKeyException e) {
        assertTrue(e.getMessage().contains("E11000 duplicate key error collection: opportunity-test.pro_mycard index: uid dup key: { : \"1\" }"));
    }

单独执行这个测试方法没有问题 如果执行整个测试类的话 这个测试方法就会通不过

原因

会在每个测试方法结束后 删除collection

@After
public void tearDown() {
    mongoTemplate.dropCollection(MyCardDO.class);
}

而Spring data mongodb 只会执行一次createIndex操作 一旦已经执行过了 之后就不会再执行了
于是之后的测试方法执行的时候 collection是没有索引存在的 故会报错

补充

一旦org.springframework.data.mapping.context.AbstractMappingContext#persistentEntities已经缓存了该Entity 那么之后就不会执行createIndex操作了

org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator#createIndex

解决

@After
public void tearDown() {
    mongoTemplate.remove(new Query(), MyCardDO.class);
}
@AfterClass
public static void finalClean() {
    mongoTemplate.dropCollection(MyCardDO.class);
}

每个方法执行完后 只是清空collection中的数据 等整个测试类执行完后才去drop

相关推荐