{"id":18329623,"url":"https://github.com/jupiter-tools/spring-test-mongo","last_synced_at":"2025-04-06T01:32:40.809Z","repository":{"id":52540672,"uuid":"159944480","full_name":"jupiter-tools/spring-test-mongo","owner":"jupiter-tools","description":"Tools suite to write integration tests for MongoDb in Spring Framework.","archived":false,"fork":false,"pushed_at":"2023-02-25T00:54:41.000Z","size":424,"stargazers_count":13,"open_issues_count":14,"forks_count":7,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-21T15:11:06.436Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jupiter-tools.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-12-01T12:55:29.000Z","updated_at":"2023-01-08T11:39:17.000Z","dependencies_parsed_at":"2022-09-18T12:02:25.035Z","dependency_job_id":null,"html_url":"https://github.com/jupiter-tools/spring-test-mongo","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jupiter-tools%2Fspring-test-mongo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jupiter-tools%2Fspring-test-mongo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jupiter-tools%2Fspring-test-mongo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jupiter-tools%2Fspring-test-mongo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jupiter-tools","download_url":"https://codeload.github.com/jupiter-tools/spring-test-mongo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247423472,"owners_count":20936621,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-05T19:18:05.525Z","updated_at":"2025-04-06T01:32:35.801Z","avatar_url":"https://github.com/jupiter-tools.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":":toc: preamble\n:sectnums:\n\n# Spring Test MongoDb\n\nimage:https://travis-ci.com/jupiter-tools/spring-test-mongo.svg?branch=master[\"Build Status\", link=\"https://travis-ci.com/jupiter-tools/spring-test-mongo\"]\nimage:https://sonarcloud.io/api/project_badges/measure?project=com.antkorwin%3Aspring-test-mongo\u0026metric=coverage[]\n\nTools to write integration tests of applications with a MongoDb persistence layer and Spring Framework.\n\n\n## Introduction\n\nSpringTestMongo is a tool to write integration tests on systems which\nused the MongoDB as a data storage.\nThis library provides you an ability to run your tests with the docker\nimage of MongoDB (by the use of Testcontainers).\n\nAlso, spring-test-mongo allows you to write tests in a more pragmatic\nmanner using annotations and extension for JUnit5.\nAlso, this library supports the JUnit4 by the using a Rule approach.\nYou can use JSON files to prepare the state of a database\nor to check this state after some activities (update, delete e.t.c).\n\n## Getting started\n\nYou need to add the next dependency:\n\n[source, xml]\n----\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.jupiter-tools\u003c/groupId\u003e\n    \u003cartifactId\u003espring-test-mongo\u003c/artifactId\u003e\n    \u003cversion\u003e0.15\u003c/version\u003e\n    \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n----\n\n## JUnit5 integration test\n\nLet's look at the example of using the TestContainers library to make integration tests.\nAnd the JUnit5 extension to make your tests more pragmatic and elegant.\n\n\n[source, java]\n----\n@MongoDbIntegrationTest \u003c1\u003e\nclass JUnit5ExampleTest {\n\n    @Autowired\n    private MongoTemplate mongoTemplate;\n\n    @Test\n    @MongoDataSet(value = \"/dataset/bar_dataset.json\")  \u003c2\u003e\n    void testPopulatingByMongoDataSet() throws Exception {\n\n        Bar simpleDoc = mongoTemplate.findById(\"55f3ed00b1375a48e618300b\", Bar.class);  \u003c3\u003e\n\n        Assertions.assertThat(simpleDoc)\n                  .isNotNull()\n                  .extracting(Bar::getId, Bar::getData)\n                  .containsOnly(\"55f3ed00b1375a48e618300b\", \"BB\");\n    }\n}\n----\n\u003c1\u003e This annotation runs MongoDB instance by the use of Testcontainers library\nand turn on SpringTestMongo which able you to use DataSets in tests\n\u003c2\u003e Initialize the state of the database from JSON file before the test execute\n\u003c3\u003e Read data from the MongoDB instance which started by the MongoDbIntegrationTest annotation\n\n\n\nLet's look at the file with a data-set(`bar_dataset.json`):\n\n[source, json]\n----\n{\n  \"com.antkorwin.springtestmongo.Bar\": [\n    {\n      \"id\": \"55f3ed00b1375a48e618300a\",\n      \"data\": \"A\"\n    },\n    {\n      \"id\": \"55f3ed00b1375a48e618300b\",\n      \"data\": \"BB\"\n    }\n  ]\n}\n----\n\n\n## JUnit4 integration test\n\nAlso, you can use the JUnit4 rule and the base abstract class\nto write integration tests in the old-style (with the use of the JUnit4 and inheritance in tests)\n\n[source, java]\n----\npublic class JUnit4ExampleTest extends BaseMongoIT {\n\n    @Test\n    @MongoDataSet(value = \"/dataset/multidocument_dataset.json\")\n    public void testPopulatingByMongoDataSet() throws Exception {\n\n        Bar simpleDoc = mongoTemplate.findById(\"55f3ed00b1375a48e618300b\", Bar.class);\n\n        Assertions.assertThat(simpleDoc)\n                  .isNotNull()\n                  .extracting(Bar::getId, Bar::getData)\n                  .containsOnly(\"55f3ed00b1375a48e618300b\", \"BB\");\n    }\n}\n----\n\n## Importing datasets before test execution\n\n`spring-test-mongo` provides you an ability to import initial data in the\nMongoDB database before starting a test execution.\nYou can describe this dataset as a JSON file with an array of MongoDB documents.\n\nFor example we consider a simple document class:\n\n[source, java]\n----\n@Document\npublic class Foo {\n    @Id\n    private String id;\n    private Date time;\n    private int counter;\n}\n----\n\nLet's look at the dataset file (`foo-init.json`) with a pare instances of this class:\n\n[source, json]\n----\n{\n  \"com.antkorwin.springtestmongo.Foo\": [  \u003c1\u003e\n    {\n      \"id\": \"77f3ed00b1375a0000000001\",\n      \"time\":1516527720001,\n      \"counter\":1\n    },{\n      \"id\": \"77f3ed00b1375a0000000002\",\n      \"time\":1516527720002,\n      \"counter\":2\n    }\n  ]\n}\n----\n\u003c1\u003e full class-reference of populated document collection\n\n\nNow we can write an integration test which will init the database from this file:\n\n[sourcem java]\n----\n@Test\n@MongoDataSet(value = \"/dataset/foo-init.json\")  \u003c1\u003e\nvoid testImportByMongoDataSetAnnotation() {\n    // Act\n    Foo fooDoc = mongoTemplate.findById(\"77f3ed00b1375a0000000001\", Foo.class);\n    // Assert\n    Assertions.assertThat(fooDoc)\n              .isNotNull()\n              .extracting(Foo::getCounter, Foo::getTime)\n              .containsOnly(1, new Date(1516527720001L));\n}\n----\n\u003c1\u003e Annotation MongoDataSet initialize the state of MongoDb from JSON file before the test execution\n\n### Multiple document types in one dataset\n\nIf you need to populate different documents collection before execution one test\nthen you can write multiple arrays of necessary types in a dataset:\n\n[source, json]\n-----\n{\n  \"com.antkorwin.springtestmongo.Bar\": [  \u003c1\u003e\n    {\n      \"id\": \"55f3ed00b1375a48e618300a\",\n      \"data\": \"A\"\n    },\n    {\n      \"id\": \"55f3ed00b1375a48e618300b\",\n      \"data\": \"BB\"\n    }\n  ],\n  \"com.antkorwin.springtestmongo.Foo\": [  \u003c2\u003e\n    {\n      \"id\": \"77f3ed00b1375a48e618300a\",\n      \"time\":1516527720000,\n      \"counter\":1\n    }\n  ]\n}\n-----\n\u003c1\u003e first document array\n\u003c2\u003e second document array\n\n### Nested documents\n\nYou can describe nested objects in your dataset.\nLet's look at the the next model:\n\n[source, java]\n----\n@Data\n@Document\npublic class FooBar {\n    @Id\n    private String id;\n    private String data;\n    private Bar bar;  \u003c1\u003e\n}\n\n@Data\n@Document\npublic class Bar {\n    @Id\n    private String id;\n    private String data;\n}\n----\n\u003c1\u003e nested object with another type\n\nso, you can describe a dataset for this example as shown below:\n\n[source, json]\n----\n{\n  \"com.jupiter.tools.spring.test.mongo.FooBar\" : [ {\n    \"id\": \"55f1dd90a1246a44e118300b\",\n    \"data\" : \"TOP LEVEL DATA\",\n    \"bar\": {\n      \"id\": \"88f3ed00b1375a48e619900c\",\n      \"data\":\"NESTED DATA\"\n    }\n  }]\n}\n----\n\n### Date and time in dataset\n\nTo set a date and time value in a field you can use\nthe next syntactic construction:\n\nimage::./images/date-time-pattern.png[date-time-pattern]\n\nFor example if you need tomorrow you can use this pattern: `[NOW]+1(DAYS)`,\nif you need a time value of three minutes ago: `[NOW]-3(MINUTES)`.\n\nValue of these fields will be prepare before run the test.\n\n[#groovy-scripting]\n### GroovyScript in datasets\n\nTo use Groovy scriptable datasets you need to add the next dependency:\n\n[sourcce, xml]\n----\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.codehaus.groovy\u003c/groupId\u003e\n    \u003cartifactId\u003egroovy-all\u003c/artifactId\u003e\n    \u003cversion\u003e2.4.6\u003c/version\u003e\n    \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n----\n\nLet's look at the next document:\n\n[source, java]\n----\n@Document\npublic class Task {\n\n    @Id\n    private String id;\n    private String title;\n    private int estimate;\n    private Date createTime;\n}\n----\n\nYou can write groovy scripts in the values of fields:\n\n[source, json]\n----\n{\n  \"com.antkorwin.springtestmongoexamples.model.Task\": [\n    {\n      \"id\": \"55f3ed00b1375a48e618300a\",\n      \"title\": \"black magic\",\n      \"estimate\": \"groovy: (1..5).sum()\",\n      \"createTime\": \"groovy: new Date(12345)\"\n    }\n  ]\n}\n----\n\nValues of these fields will be evaluated before populate data set in the database.\nAnd you can write the next test with expected values of this fields:\n\n[source, java]\n----\n@Test\n@MongoDataSet(cleanBefore = true,  \u003c1\u003e\n              cleanAfter = true,   \u003c2\u003e\n              value = \"dataset/init_task_groovy.json\")\nvoid groovyInitTest() {\n    Task task = taskService.get(\"55f3ed00b1375a48e618300a\");\n    assertThat(task).extracting(Task::getEstimate, Task::getCreateTime)\n                    .contains(1 + 2 + 3 + 4 + 5, new Date(12345));\n}\n----\n\u003c1\u003e drops all collection before populate a dataset\n\u003c2\u003e clean database after the test execution\n\n### JavaScript in datasets\n\nUnlike Groovy scripts, Javascript comes by default in JDK and you\ndon't need some extra dependencies to work with JavaScript.\n\nLet's consider the next simple document class:\n\n[source, java]\n----\n@Document\npublic class Bar {\n    @Id\n    private String id;\n    private String data;\n}\n----\n\nand make the dataset file `javascript-dataset.json`:\n\n[source, json]\n----\n{\n   \"com.antkorwin.springtestmongo.Bar\": [\n     {\n       \"id\": \"55f3ed00b1375a48e618300a\",\n       \"data\": \"js: 2+3\"\n     }\n   ]\n}\n----\n\nAnd now we expecting a successful result of this test:\n\n[source, java]\n----\n@Test\n@MongoDataSet(value = \"javascript-dataset.json\")\npublic void jsDataset() throws Exception {\n\n    Bar simpleDoc = mongoTemplate.findById(\"55f3ed00b1375a48e618300a\", Bar.class);\n\n    Assertions.assertThat(simpleDoc)\n              .isNotNull()\n              .extracting(Bar::getData)\n              .containsOnly(5);\n}\n----\n\n### Immutable data set\n\nIf you need to assert that data in the mongodb do not change after\ntest execution then you can use parameter `readOnly` in the annotation\n`MongoDataSet` as you can see below:\n\n[source, java]\n----\n@Test\n@MongoDataSet(value = \"/dataset/foo-init.json\", readOnly = true)\nvoid testImportByMongoDataSetAnnotation() {\n    Foo fooDoc = mongoTemplate.findById(\"77f3ed00b1375a0000000001\", Foo.class);\n    // if you change data in MongoDB here, then this test will fail.\n}\n----\n\n\n## Expecting the state of the database after a test execution\n\n`spring-test-mongo` provides you an ability to declare dataset that you\nexpect in MongoDB after test execution.\n\nLet's try to use it by the testing creation of new Task:\n\n[source, java]\n----\n@Test\n@ExpectedMongoDataSet(\"dataset/create_task_expected.json\")\nvoid create() {\n    mongoTemplate.save(new Task(\"black magic\", 123));\n}\n----\n\ncontent of the expected dataset:\n\n[source, json]\n----\n{\n  \"com.antkorwin.springtestmongoexamples.model.Task\": [\n    {\n      \"title\": \"black magic\",\n      \"estimate\": 123\n    }\n  ]\n}\n----\n\n\n### Using regular-expressions in datasets\n\nAnnotation ExpectedDataSet provide you an ability\nto use regular expressions in JSON datasets. For example you can\ndescribe expected field as: `regex: ^data-.$`\n\nLet's look at the dataset of ContactInfo documents:\n\n[source, json]\n----\n{\n  \"com.antkorwin.springtestmongoexamples.model.ContactInfo\": [\n    {\n      \"title\": \"e-mail\",\n      \"value\": \"regex: \\\\S+@\\\\S+\\\\.\\\\S+$\"  \u003c1\u003e\n    }\n  ]\n}\n----\n\u003c1\u003e using regex to check email value from database\n\n### Date \u0026 Time matching\n\nIt works the same as import dataset but\nneed to use prefix `date-match:` instead od `date:`\nin the expected value of fields:\n\n[source,java]\n----\n{\n  \"com.antkorwin.springtestmongo.Foo\": [\n    {\n      \"time\": \"date-match:[NOW]\",\n      \"counter\" : 1\n    },\n    {\n      \"time\":\"date-match:[NOW]+3(MINUTES)\",\n      \"counter\" : 2\n    }\n  ]\n}\n----\n\nNow we can run this test:\n\n[source, java]\n----\n@Test\n@ExpectedMongoDataSet(\"dataset/expect_with_dates.json\")\nvoid dateTimeNow() {\n   Date now = new Date();\n   Date plus3min = new Date(now.getTime() + TimeUnit.MINUTES.toMillis(3));\n   mongoTemplate.save(new Foo(now, 1));\n   mongoTemplate.save(new Foo(plus3min, 2));\n}\n----\n\nDate matching checks time with a threshold value, and you can set amount of this\nthreshold in the date-matcher like this: `date-match:[NOW]+25(SECONDS){THR=0}`\nBy default threshold value is 10 000 milliseconds.\n\nimage::./images/date-match-pattern.png[date-match-pattern]\n\nYou can see syntactic of the match date pattern on the picture above.\n\n### JavaScript matching\n\nYou can use javascript in expected datasets:\n\n[source, json]\n----\n{\n  \"com.antkorwin.springtestmongo.Foo\": [\n    {\n      \"counter\" : 17\n    },\n    {\n      \"counter\" : \"js-match: value % 2 == 0\"  \u003c1\u003e\n    }\n  ]\n}\n----\n\u003c1\u003e javascript expression expected even value in database\n\n\n[source, java]\n----\n@Test\n@MongoDataSet(cleanBefore = true, cleanAfter = true)\n@ExpectedMongoDataSet(\"js_match.json\")\nvoid matchJavaScript() {\n    mongoTemplate.save(new Bar(17));\n    mongoTemplate.save(new Bar(32));\n}\n----\n\n### Groovy matching\n\nAlso, you can use groovy scripts for matching values after a test execution.\nTo work with groovy you need to add it in dependencies (see \u003c\u003cgroovy-scripting\u003e\u003e section)\n\n\n[source, json]\n----\n{\n  \"com.antkorwin.springtestmongo.Foo\": [\n    {\n      \"counter\" : \"groovy-match: value == 10+7\"\n    },\n    {\n      \"counter\" : \"groovy-match: value == (1..10).sum()\"\n    }\n  ]\n}\n----\n\nand now we can run this test:\n\n[source, java]\n----\n@Test\n@MongoDataSet(cleanBefore = true, cleanAfter = true)\n@ExpectedMongoDataSet(\"js_match.json\")\nvoid matchJavaScript() {\n    mongoTemplate.save(new Bar(17));\n    mongoTemplate.save(new Bar(55));\n}\n----\n\n## Use GeoJson in data sets\n\nWith this library you can use different GeoJson data types in\nyour tests. Let's consider the next document:\n\n[source, java]\n----\n@Document\npublic class StarShip {\n    @Id\n    private String id;\n    private String name;\n    private int armor;\n    private int damage;\n    private GeoJsonPoint location;\n    private GeoJsonPolygon shape;\n}\n----\n\n### Export GeoJson data after tests execution in the dataset\n\nWhen you use `@ExportMongoDataSet` annotation in tests\nthen documents from the database will be serialized\nto the target file in a next way:\n\n[souce, json]\n----\n{\n  \"com.jupiter.tools.spring.test.mongo.documents.StarShip\": [\n    {\n      \"id\": \"5cbbff29921376648d6f4e81\",\n      \"name\": \"Dreadnought\",\n      \"armor\": 100,\n      \"damage\": 50,\n      \"location\": {\n        \"type\": \"Point\",\n        \"coordinates\": [20.0, 40.0]\n      },\n      \"shape\": {\n        \"type\": \"Polygon\",\n        \"coordinates\": [\n          [\n            [20.0, 40.0],\n            [22.0, 42.0],\n            [22.0, 40.0],\n            [20.0, 42.0]\n          ]\n        ]\n      }\n    }\n  ]\n}\n----\n\nexample of the test with the exporting dataset:\n\n[source, java]\n----\n@Test\n@ExportMongoDataSet(outputFile = \"target/dataset/export.json\")\nvoid exportPolygon() {\n\n    Point p1 = new Point(20, 40);\n    Point p2 = new Point(22, 42);\n    Point p3 = new Point(22, 40);\n    Point p4 = new Point(20, 42);\n\n    StarShip dreadnought = StarShip.builder()\n                                   .name(\"Dreadnought\")\n                                   .armor(100)\n                                   .damage(50)\n                                   .location(new GeoJsonPoint(20, 40))\n                                   .shape(new GeoJsonPolygon(p1, p2, p3, p4))\n                                   .build();\n\n    mongoTemplate.save(dreadnought);\n}\n----\n\n### Expected GeoJson in the data set\n\nLet's look at the sample of the searching an object in MongoDB within the (GeoJson) rectangle boundary:\n\n[source, java]\n----\n@Test\n@MongoDataSet(value = \"dataset/geo/geo_within.json\")\nvoid findWithinRectangle() {\n    // Act\n    GeoJsonPolygon boundary = new GeoJsonPolygon(new Point(0, 0),\n                                                 new Point(10, 0),\n                                                 new Point(10, 10),\n                                                 new Point(0, 10),\n                                                 new Point(0, 0));\n\n    Query query = new Query();\n    query.addCriteria(Criteria.where(\"location\")\n                              .within(boundary));\n    // Act\n    List\u003cStarShip\u003e ships = mongoTemplate.find(query, StarShip.class);\n\n    // Assert\n    assertThat(ships).hasSize(1);\n    assertThat(ships.get(0).getName()).isEqualTo(\"x-wing\");\n}\n----\n\nwe used a next data set with two objects in the file `dataset/geo/geo_within.json` :\n\n[source, json]\n----\n{\n  \"com.jupiter.tools.spring.test.mongo.documents.StarShip\": [\n    {\n      \"id\": \"5cbaa745921376602705886f\",\n      \"name\": \"x-wing\",\n      \"location\": {\n        \"type\": \"Point\",\n        \"coordinates\": [\n          1.0,\n          5.0\n        ]\n      }\n    },\n    {\n      \"id\": \"5cbaa74592137660270588ff\",\n      \"name\": \"falcon\",\n      \"location\": {\n        \"type\": \"Point\",\n        \"coordinates\": [\n          15.0,\n          10.0\n        ]\n      }\n    }\n  ]\n}\n----\n\n\n## MongoDb transactions support\n\nSince 0.15 version of the `spring-test-mongo` supports transactions in mongodb.\nMongoDB currently supports transactions over a replica set,\nyou can read about this feature here: https://www.baeldung.com/spring-data-mongodb-transactions","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjupiter-tools%2Fspring-test-mongo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjupiter-tools%2Fspring-test-mongo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjupiter-tools%2Fspring-test-mongo/lists"}