EmbedMongo用于集成测试

时间:2014-03-28 23:02:24

标签: spring mongodb integration-testing

我正在寻找事务支持来回滚更改,同时测试我在Spring + RESt + Mongo 2.4中编写的应用程序。但由于我们不能将事务用于mongodb,因此它不可能实现。在搜索集成测试时,我发现很少有关于embedMongo进行集成测试的链接。您还可以通过在某处运行专用的mongo db实例来进行集成测试。嵌入mongo提供了哪些特殊功能?我没有找到它的优秀文档,它是否在Apache许可下?

3 个答案:

答案 0 :(得分:2)

  

我正在寻找事务支持来回滚更改,同时测试我在Spring + RESt + Mongo 2.4中编写的应用程序。但由于我们不能将事务用于mongodb,因此它不可能实现。

不支持交易,但您确实有一些替代方法可以在测试时回滚更改:

  • 在设置或拆除单元测试期间根据需要创建/重置数据
  • 为您的初始数据集播种,并在测试期间使用mongod启动--syncdelay=0,以便不会将新数据写入磁盘(嵌入式MongoDB建议将此作为"snapshot"方法)
  

在搜索集成测试时,我发现很少有关于embedMongo进行集成测试的链接。您还可以通过在某处运行专用的mongo db实例来进行集成测试。嵌入mongo提供了哪些特殊功能?

Embedded MongoDB是标准MongoDB Server二进制文件的包装器,旨在帮助进行单元测试。包装器的“特殊功能”只是通过单元测试启动/停止MongoDB实例的功能。

另见Embedded MongoDB when running integration tests的评论。

  

我没有找到很好的文档,它是否在Apache许可下?

GitHub上的"Embedded MongoDB"源文件建议使用Apache 2.0许可证。

MongoDB服务器二进制文件将使用standard MongoDB Server community license,即AGPL v3.0。

答案 1 :(得分:1)

在集成测试中,您只需使用@DirtiesContext annotation

此示例将在每个测试方法后重置MongoDB数据库:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class OrderControllerIT {

此注释也可以与@DataMongoTest一起使用。这可以使用flapdoodle Embedded Mongo

很好地工作

答案 2 :(得分:0)

我使用以下机制来模拟@Transactional测试

创建了一个模拟回滚的简单类

  • 在测试前保存数据库状态的快照
  • 在测试后恢复它。

或者,如果所有测试都以相同的DB状态启动,则第一次保存快照,然后在每次其他测试之前恢复它。

样本测试助手

@Service
public class MongoTestHelper {
    @Autowired
    private MongoTemplate mongoTemplate;

    private Map<String, List<Document>> snapshot = null;

    public void createSnapshot() {
        this.snapshot = new HashMap<>();
        mongoTemplate.getCollectionNames().forEach(collectionName ->
            {
                List<Document> collectionDocs = new ArrayList<>();
                mongoTemplate.getCollection(collectionName).find(Document.class)
                    .forEach((Consumer<? super Document>) collectionDocs::add);
                snapshot.put(collectionName, collectionDocs);
            }
        );
    }

    public void restoreSnapshot() {
        snapshot.keySet().forEach(collectionName -> {
            mongoTemplate.dropCollection(collectionName);
            snapshot.get(collectionName).forEach(d ->
                mongoTemplate.insert(d, collectionName)
            );
        });
    }

    public boolean hasSnapshot() {
        return this.snapshot != null;
    }
}

用法

在我提出的所有Integration测试中共享的setUp方法AbstractIntTest类中:

public void setUp() { 
    if (mongoHelper.hasSnapshot()) {
        // if there is a saved snapshot just restore it
        mongoHelper.restoreSnapshot();
    } else {
        // this is the very first run: create the snapshot
        mongoHelper.createSnapshot();
    }
}

PS。您可以扩展以下方法来保存/恢复索引和其他与数据库相关的事物。