Java 使用 mongodb 数据库进行测试
Java test with mongodb database
描述
我正在 mobgoDB 数据库中测试批量插入,在 @BeforeEach
方法中我实例化了数据库,在 @AfterEach
中我删除了在 puzzles-todaycollection.
但是最后一个总是失败,结果是随机的,有时测试通过有时显示这个367或366或364或364。
我添加了 @RepeatedTest(4)
以确保它没有变化。
代码:
Class 测试
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
中克隆存储库
显示错误:
但这个结果是随机的,有时测试通过有时会显示错误。
有人知道如何解决这个问题吗?
你遇到的问题不是测试问题,而是实现问题。
看:
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()
就可以摆脱复杂的并行性。
描述
我正在 mobgoDB 数据库中测试批量插入,在 @BeforeEach
方法中我实例化了数据库,在 @AfterEach
中我删除了在 puzzles-todaycollection.
但是最后一个总是失败,结果是随机的,有时测试通过有时显示这个367或366或364或364。
我添加了 @RepeatedTest(4)
以确保它没有变化。
代码:
Class 测试
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
显示错误:
但这个结果是随机的,有时测试通过有时会显示错误。
有人知道如何解决这个问题吗?
你遇到的问题不是测试问题,而是实现问题。 看:
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()
就可以摆脱复杂的并行性。