【问题标题】:Java test with mongodb database使用 mongodb 数据库进行 Java 测试
【发布时间】:2022-01-04 18:43:12
【问题描述】:

说明

我在 mobgoDB 数据库中测试批量插入,在 @​​987654324@ 方法中我实例化数据库,在@AfterEach 我删除在 puzzles-today 集合中创建的所有文档。

但最后一个总是失败,有随机结果,有时测试通过有时显示这个367 or 366 or 364 or 364.

我添加了@RepeatedTest(4) 以确保它不会发生变化。

代码:

类测试

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.List;

import com.github.mathieusoysal.codingame_stats.CodinGame;
import com.github.mathieusoysal.codingame_stats.puzzle.Puzzle;

import org.bson.Document;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;

import io.github.mathieusoysal.util.MongoDBMockTest;

public class PuzzleDaoTest extends MongoDBMockTest {

    private PuzzlesDao puzzleDao;

    @BeforeEach
    public void setUp() throws Exception {
        super.setUp();
        puzzleDao = new PuzzlesDao(mongoClient, "CodinGame-stats");
    }

    @AfterEach
    public void tearDown() throws Exception {
        mongoClient.getDatabase("CodinGame-stats")
                .getCollection(PuzzlesDao.PUZZLES_HISTORY_COLLECTION)
                .deleteMany(new Document());
        super.tearDown();
    }

    @Test
    void testSaveAll_shouldReturnTrue_withTwoPuzzles() {
        List<Puzzle> puzzles = new CodinGame().getPuzzles().subList(0, 2);
        assertTrue(puzzleDao.saveAll(puzzles));
    }

    @Test
    void testSaveAll_shouldAugmentCollectionSize_withTwoPuzzles() {
        List<Puzzle> puzzles = new CodinGame().getPuzzles().subList(0, 2);
        puzzleDao.saveAll(puzzles);
        assertEquals(puzzles.size(), countDocuments());
    }

    @RepeatedTest(4)
    void testSaveAll_shouldAugmentCollectionSize_withAllPuzzles() {
        List<Puzzle> puzzles = new CodinGame().getPuzzles();
        puzzleDao.saveAll(puzzles);
        assertEquals(puzzles.size(), countDocuments());
    }

    private long countDocuments() {
        return mongoClient.getDatabase("CodinGame-stats")
                .getCollection(PuzzlesDao.PUZZLES_HISTORY_COLLECTION)
                .countDocuments();
    }

}

克隆项目

要轻松复制此内容,您可以克隆 dev 分支 https://github.com/MathieuSoysal/CodinGame-Puzzles-stats-saver/tree/dev 中的存储库

错误显示:

但是这个结果是随机的,有时测试通过有时会显示错误。

有人有办法解决这个问题吗?

【问题讨论】:

  • 这里发生了太多未知的事情。我建议您创建一个包含所有详细信息的最小示例来复制您的问题。否则外界很难搞清楚。
  • @johanneslink 感谢您的反馈,我添加了更多细节来重现问题。
  • 失败信息是什么?
  • 我编辑了我的问题以添加失败消息。
  • 如果您想提高有人会帮助您解决问题的机会,请尽可能轻松地为他们复制问题。必须将我自己的 pom.xml 放在一起并将几个源复制到一个我必须自己配置的项目中,这远远超出了我的门槛。其他人的里程可能会有所不同。

标签: java mongodb unit-testing testing junit5


【解决方案1】:

您遇到的问题不是测试问题,而是实施问题。 看:

class PuzzlesDao...
    public boolean saveAll(List<Puzzle> puzzles) {
        List<WriteModel<Document>> bulkWrites = new ArrayList<>();
        GsonBuilder builder = new GsonBuilder();
        Gson gson = builder.create();
        puzzles.parallelStream()
                .forEach(puzzle -> bulkWrites.add(new InsertOneModel<>(Document.parse(gson.toJson(puzzle)))));
        BulkWriteOptions bulkWriteOptions = new BulkWriteOptions().ordered(false);
        BulkWriteResult bulkWriteResult = collection.bulkWrite(bulkWrites, bulkWriteOptions);
        return bulkWriteResult.wasAcknowledged();
    }

您正在使用parallelStream(),而没有像collect(..)count() 这样的关闭操作。当批量操作已经运行时,forEach 代码仍在执行。因此,由此产生的行为是不可预测的。一种启发式方法是永远不要在forEach() 中使用任何副作用。如果必须,那么在我看来,使用简单的 for 循环是更好的选择。

我建议进行以下更改:

public boolean saveAll(List<Puzzle> puzzles) {
    GsonBuilder builder = new GsonBuilder();
    Gson gson = builder.create();
    List<WriteModel<Document>> bulkWrites =
            puzzles.parallelStream()
                    .map(puzzle -> new InsertOneModel<>(Document.parse(gson.toJson(puzzle))))
                    .collect(Collectors.toList());
    BulkWriteOptions bulkWriteOptions = new BulkWriteOptions().ordered(false);
    BulkWriteResult bulkWriteResult = collection.bulkWrite(bulkWrites, bulkWriteOptions);
    return bulkWriteResult.wasAcknowledged();
}

我个人几乎从不使用parallelStream(),除非我可以证明它以一种有价值的方式提高了性能,而它通常不会。 仅使用 stream() 就可以摆脱复杂的并行性。

【讨论】:

  • 感谢您的回答!我只是更改了.toList() 而不是.collect(Collectors.toList())
猜你喜欢
  • 1970-01-01
  • 2020-07-10
  • 2019-04-18
  • 2011-06-02
  • 2023-03-15
  • 1970-01-01
  • 2021-12-17
  • 2022-08-02
  • 2014-02-26
相关资源
最近更新 更多