{"id":18329618,"url":"https://github.com/jupiter-tools/spring-boot-extensions","last_synced_at":"2025-06-25T05:41:57.634Z","repository":{"id":37285203,"uuid":"167120824","full_name":"jupiter-tools/spring-boot-extensions","owner":"jupiter-tools","description":"A lot of JUnit5 Extensions to work with Spring Boot.","archived":false,"fork":false,"pushed_at":"2023-02-25T00:44:56.000Z","size":784,"stargazers_count":38,"open_issues_count":12,"forks_count":6,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-06T01:32:35.840Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://jupiter-tools.com","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":"2019-01-23T05:07:42.000Z","updated_at":"2025-01-06T08:23:13.000Z","dependencies_parsed_at":"2022-08-18T22:11:32.503Z","dependency_job_id":null,"html_url":"https://github.com/jupiter-tools/spring-boot-extensions","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/jupiter-tools/spring-boot-extensions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jupiter-tools%2Fspring-boot-extensions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jupiter-tools%2Fspring-boot-extensions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jupiter-tools%2Fspring-boot-extensions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jupiter-tools%2Fspring-boot-extensions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jupiter-tools","download_url":"https://codeload.github.com/jupiter-tools/spring-boot-extensions/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jupiter-tools%2Fspring-boot-extensions/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261814834,"owners_count":23213809,"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:04.736Z","updated_at":"2025-06-25T05:41:57.604Z","avatar_url":"https://github.com/jupiter-tools.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":":toc: preamble\n\n# JUnit5 Spring Boot Extensions\n\nimage:https://travis-ci.com/jupiter-tools/spring-boot-extensions.svg?branch=master[\"Build Status\", link=\"https://travis-ci.com/jupiter-tools/spring-boot-extensions\"]\nimage:https://codecov.io/gh/jupiter-tools/spring-boot-extensions/branch/master/graph/badge.svg[link =\"https://codecov.io/gh/jupiter-tools/spring-boot-extensions\"]\n\n## Database specific tests\n\nimage:./images/jpa-containers.png[jpa containers extension scheme]\n\n### TraceSql Extension\n\n\nProvide you an ability to check SQL statement execution after tests.\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-jpa\u003c/artifactId\u003e\n    \u003cversion\u003e0.2\u003c/version\u003e\n\u003c/dependency\u003e\n----\n\nAnd now, you can assert a count of insert operations after save an entity:\n\n[source, java]\n----\n@ExtendWith(TraceSqlExtension.class)\n@ExtendWith(SpringExtension.class)\n@SpringBootTest\nclass TraceSqlExtensionTest {\n\n    @Autowired\n    private FooRepository fooRepository;\n\n    @Test\n    void testInsert() {\n        // Act\n        fooRepository.save(new Foo(\"any data\"));\n        // Assert\n        AssertSqlCount.assertInsertCount(1);\n    }\n}\n----\n\nAlso, you can use annotation on the test case to assert the expected count of executed queries:\n\n[source, java]\n----\n@Test\n@ExpectedSqlQuery(type = INSERT, count = 1)\nvoid testInsert() {\n    fooRepository.save(new Foo(\"data\"));\n}\n\n@Test\n@ExpectedSqlQuery(type = SELECT, count = 1)\nvoid testSelect() {\n    fooRepository.findAll();\n}\n----\n\n\n### PostgreSQL Extension\n\nTo run the docker postgres image by the test-containers library\nin your integration test, you can use PostgresTcExtension.\n\n[source,xml]\n----\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.jupiter-tools\u003c/groupId\u003e\n    \u003cartifactId\u003espring-test-postgres\u003c/artifactId\u003e\n    \u003cversion\u003e0.2\u003c/version\u003e\n\u003c/dependency\u003e\n----\n\nLet's try to execute a stored procedure specific to PostgreSQL:\n\n[source, java]\n----\n@DataJpaTest\n@ExtendWith(SpringExtension.class)\n@ExtendWith(PostgresTcExtension.class)\n@ExtendWith(TraceSqlExtension.class)\n@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)\nclass PostgresTcExtensionTest {\n\n    @PersistenceContext\n    private EntityManager entityManager;\n\n    @Test\n    @Sql(\"/stored_functions/test_func.sql\")\n    void testStoredFunc() {\n        // Arrange\n        StoredProcedureQuery query = entityManager.createStoredProcedureQuery(\"rnd\");\n        // Act\n        query.execute();\n        // Assert\n        List resultList = query.getResultList();\n        int rnd = (int) resultList.get(0);\n        Assertions.assertThat(rnd).isEqualTo(123);\n    }\n}\n----\n\nThis library provides a wide system of meta-annotations to\nsimplified writing integration test's configuration.\n\nFor example, you can write:\n\n[source, java]\n----\n@EnablePostgresDataTest\nclass EnablePostgresDataTestTest {\n    ...\n}\n----\n\ninstead of:\n\n[source, java]\n----\n@DataJpaTest\n@ExtendWith(SpringExtension.class)\n@ExtendWith(PostgresTcExtension.class)\n@ExtendWith(TraceSqlExtension.class)\n@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)\nclass PostgresTcExtensionTest {\n    ...\n}\n----\n\nyou can see at whole postgres annotation system at the next picture::\n\nimage:./images/pg-annotations.png[postgres annotation system]\n\nYou can build a necessary test configuration by using annotations which you need. Meta-annotations is a beautiful mechanism which will you a making configuration in a declarative style.\n\n\n### MySql Extension\n\nMySqlTcExtension runs the mysql docker image and set spring properties\nin the configuration to use this datasource in tests.\n\n[source,xml]\n----\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.jupiter-tools\u003c/groupId\u003e\n    \u003cartifactId\u003espring-test-mysql\u003c/artifactId\u003e\n    \u003cversion\u003e0.2\u003c/version\u003e\n\u003c/dependency\u003e\n----\n\nYou can use this extension by the applying of `EnableMySqlTestContainersExtension` annotation or\nyou can use `@EnableMySqlDataTest` to write a test with the DataJpa context configuration:\n\n[source, java]\n----\n@EnableMySqlDataTest\nclass EnableMySqlDataTestTest {\n\n    @Autowired\n    private FooRepository repository;\n\n    @Test\n    @Commit\n    @DataSet(cleanBefore = true, cleanAfter = true)\n    @ExpectedDataSet(value = \"/datasets/expected.json\", ignoreCols = \"ID\")\n    void testCreate() throws Exception {\n        repository.saveAndFlush(new Foo(\"any data\"));\n    }\n}\n----\n\n\nAs well as for the PostgreSQL in this library there is a system of meta-annotations for the MySql:\n\nimage:./images/mysql-annotations.png[mysql annotation system]\n\n\n## Messaging systems\n\nimage:./images/jms.png[messaging system annotations]\n\n### RabbitMq Extension\n\n`RabbitMqTcExtension` runs the RabbitMq docker image by the TestContainers library\nand configure SpringBoot properties to work with this container.\n\n[source,xml]\n----\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.jupiter-tools\u003c/groupId\u003e\n    \u003cartifactId\u003espring-test-rabbitmq\u003c/artifactId\u003e\n    \u003cversion\u003e0.2\u003c/version\u003e\n\u003c/dependency\u003e\n----\n\nNow we can run RabbitMq in tests and send a message in a real queue:\n\n[source, java]\n----\n@SpringBootTest\n@ExtendWith(SpringExtension.class)\n@ExtendWith(RabbitMqTcExtension.class)\nclass EnableRabbitMqTestTest {\n\n    @Autowired\n    private AmqpTemplate amqpTemplate;\n\n    @Test\n    void testSend() {\n        amqpTemplate.convertAndSend(\"test-queue\", \"123\");\n        ...\n\n    }\n}\n----\n\nAs well as with database specific tests, in this case, you can use meta-annotation to write tests more pragmatic:\n\n[source, java]\n----\n@EnableRabbitMqTest\nclass EnableRabbitMqTestTest {\n   ...\n}\n----\n\nAlso, you can assert the sending of messages in the selected queue:\n\n[source, java]\n----\n@EnableRabbitMqTest\npublic class ExpectedMessageTest {\n\n    @Autowired\n    private AmqpTemplate amqpTemplate;\n\n    @Test\n    @ExpectedMessage(queue = \"test-queue\", message = \"123\")\n    void testSend() throws InterruptedException {\n        amqpTemplate.convertAndSend(\"test-queue\", \"123\");\n    }\n}\n----\n\nAlso, you can assert the receiving of multiple messages:\n\n[source, java]\n----\n@Autowired\nprivate AmqpTemplate amqpTemplate;\n\n@Test\n@ExpectedMessages(queue = \"test-queue\",  \u003c1\u003e\n                  messagesFile = \"/datasets/expected_messages.json\")  \u003c2\u003e\nvoid testSendListOfMessages() {\n    // first type:\n    amqpTemplate.convertAndSend(\"test-queue\", new Foo(\"123\"));\n    // second type:\n    amqpTemplate.convertAndSend(\"test-queue\", new Bar(\"AAA\",1));\n    amqpTemplate.convertAndSend(\"test-queue\", new Bar(\"BBB\",2));\n    amqpTemplate.convertAndSend(\"test-queue\", new Bar(\"CCC\",3));\n}\n----\n\u003c1\u003e queue name\n\u003c2\u003e file with expected messages in JSON format\n\nContent of the `expected_messages.json` :\n[source,json]\n----\n{\n  \"com.jupiter.tools.spring.test.rabbitmq.extension.pojo.Foo\": [\n    {\n      \"value\":\"123\"\n    }\n  ],\n  \"com.jupiter.tools.spring.test.rabbitmq.extension.pojo.Bar\":[\n    {\n      \"name\":\"AAA\",\n      \"count\":1\n    },\n    {\n      \"name\":\"BBB\",\n      \"count\":2\n    },\n    {\n      \"name\":\"CCC\",\n      \"count\":3\n    }\n  ]\n}\n----\n\n### ActiveMq Extension\n\nYou can run the ActiveMq docker image by the using of `EnableActiveMqTestContainers` annotation.\n\nYou need to use the next dependency:\n\n[source,xml]\n----\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.jupiter-tools\u003c/groupId\u003e\n    \u003cartifactId\u003espring-test-activemq\u003c/artifactId\u003e\n    \u003cversion\u003e0.2\u003c/version\u003e\n\u003c/dependency\u003e\n----\n\nimage:./images/activemq-annotations.png[activemq annotations]\n\nIf you need to check a sending of messages then you can use the `ExpectedMessage` annotation:\n\n[source, java]\n----\n@SpringBootTest\n@EnableActiveMqTest\npublic class SendMessageTest {\n\n    @Autowired\n    private JmsTemplate jmsTemplate;\n\n    @Test\n    @ExpectedMessage(queue = \"test-queue\", message = \"123\")\n    void testSend() {\n        jmsTemplate.convertAndSend(\"test-queue\", \"123\");\n    }\n\n    @TestConfiguration\n    public static class TestConfig {\n        @Bean\n        public Queue testQueue() {\n            return new Queue(\"test-queue\");\n        }\n    }\n}\n----\n\nAlso, you can assert the receiving of multiple messages:\n\n[source, java]\n----\n@Test\n@ExpectedMessages(queue = \"test-queue\",  \u003c1\u003e\n                  messagesFile = \"/datasets/expected_messages.json\")  \u003c2\u003e\nvoid testSendListOfMessages() {\n    // first type:\n    jmsTemplate.convertAndSend(\"test-queue\", new Foo(\"123\"));\n    // second type:\n    jmsTemplate.convertAndSend(\"test-queue\", new Bar(\"AAA\",1));\n    jmsTemplate.convertAndSend(\"test-queue\", new Bar(\"BBB\",2));\n    jmsTemplate.convertAndSend(\"test-queue\", new Bar(\"CCC\",3));\n}\n----\n\u003c1\u003e queue name\n\u003c2\u003e file with expected messages in JSON format\n\nContent of the `expected_messages.json` :\n[source,json]\n----\n{\n  \"com.jupiter.tools.spring.test.activemq.extension.expected.Foo\": [\n    {\n      \"value\":\"123\"\n    }\n  ],\n  \"com.jupiter.tools.spring.test.activemq.extension.expected.Bar\":[\n    {\n      \"name\":\"AAA\",\n      \"count\":1\n    },\n    {\n      \"name\":\"BBB\",\n      \"count\":2\n    },\n    {\n      \"name\":\"CCC\",\n      \"count\":3\n    }\n  ]\n}\n----\n\n\n## Embedded Web Server\n\nLet's consider the next microservice based application:\n\nimage:./images/embedded-web.png[embedded web services tests]\n\nYou can test inter-service communication by the running an embedded\nweb server with a mocked external controller and send HTTP requests to this server.\n\n[source,xml]\n----\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.jupiter-tools\u003c/groupId\u003e\n    \u003cartifactId\u003espring-test-web\u003c/artifactId\u003e\n    \u003cversion\u003e0.2\u003c/version\u003e\n\u003c/dependency\u003e\n----\n\nLet's test requesting to the template-service by the using of embedded server:\n\n[source, java]\n----\n@EnableEmbeddedWebServerTest \u003c1\u003e\n@RedirectRibbonToEmbeddedWebServer(\"template-service\")  \u003c2\u003e\nclass RedirectRibbonExtensionTest {\n\n    @Autowired\n    private RestTemplate restTemplate;\n\n    @Test\n    void testRedirect() {\n        // Act\n        String result = restTemplate.getForObject(\"http://template-service/templates/{template}\",\n                                                String.class,\n                                                \"balance-template\");\n        // Assert\n        assertThat(result).isEqualTo(\"{user} balance = {value}\");\n    }\n\n    @TestConfiguration\n    public static class TestCfg {\n\n        @Bean\n        @LoadBalanced\n        public RestTemplate restTemplate() {\n            return new RestTemplate();\n        }\n\n        @RestController\n        @RequestMapping(\"/templates\")\n        public class TestApi {\n\n            @GetMapping(\"/{template}\")\n            public String getLength(@PathVariable(\"template\") String template) {\n                return \"{user} balance = {value}\";\n            }\n        }\n    }\n }\n----\n\u003c1\u003e bind the embedded server to an available TCP-port\n\u003c2\u003e resolve the client name(\"template-service\") to an embedded server url\n\nIf you want to run different web servers in one test suite\nthen you need to use a different port to each server.\nAnd you need to be sure that selected port is available.\n\nAnnotation `EnableEmbeddedWebServerTest` bind a random available TCP port to the server.port property of the Spring Framework.\n\n`RedirectRibbonToEmbeddedWebServer` redirects all requests from any ribbon\nclients to embedded server, by default (if you don't set the value of this annotation).\n\n\n## Examples\n\nhttps://github.com/jupiter-tools/spring-boot-extensions-demo","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjupiter-tools%2Fspring-boot-extensions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjupiter-tools%2Fspring-boot-extensions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjupiter-tools%2Fspring-boot-extensions/lists"}