{"id":21901574,"url":"https://github.com/amadr-95/spring-boot-testing","last_synced_at":"2025-07-22T13:34:18.531Z","repository":{"id":246812232,"uuid":"822253784","full_name":"amadr-95/spring-boot-testing","owner":"amadr-95","description":"Unit Testing, Integration Testing, Testing External Services, Mocking with Mockito, Test Driven Development (TDD) and more.","archived":false,"fork":false,"pushed_at":"2024-06-30T18:08:02.000Z","size":36,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-22T06:17:45.321Z","etag":null,"topics":["integration-testing","mockito","tdd","testing","unit-testing"],"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/amadr-95.png","metadata":{"files":{"readme":"README.md","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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-30T18:02:59.000Z","updated_at":"2024-07-01T09:10:17.000Z","dependencies_parsed_at":null,"dependency_job_id":"9fe4276d-2a8e-4ed7-8a19-93cc1153aa8c","html_url":"https://github.com/amadr-95/spring-boot-testing","commit_stats":null,"previous_names":["amadr-95/spring-boot-testing"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/amadr-95/spring-boot-testing","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amadr-95%2Fspring-boot-testing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amadr-95%2Fspring-boot-testing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amadr-95%2Fspring-boot-testing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amadr-95%2Fspring-boot-testing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amadr-95","download_url":"https://codeload.github.com/amadr-95/spring-boot-testing/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amadr-95%2Fspring-boot-testing/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266506182,"owners_count":23940019,"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","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["integration-testing","mockito","tdd","testing","unit-testing"],"created_at":"2024-11-28T15:14:21.597Z","updated_at":"2025-07-22T13:34:18.511Z","avatar_url":"https://github.com/amadr-95.png","language":"Java","readme":"# Spring Boot Testing\n\n## Overview\n\nThis course has covered the following aspects:\n\n- Unit Testing\n- Integration Testing\n- Testing External Services (Stripe)\n- Mocking with Mockito\n- Test Driven Development -`TDD`\n\n## Architecture Diagram\n\n- The diagram shows the different units tested in isolation as well as the integration test that covers the whole\n  system.\n  \n  ![diagram](https://github.com/amadr-95/spring-boot-testing/assets/122611230/4c110060-b775-4789-a024-2595756376d5)\n\n\n## Tests Coverage\n  ![coverage](https://github.com/amadr-95/spring-boot-testing/assets/122611230/9be7967d-391f-4b78-8641-ec3b9b88bedc)  \n  \n  ![tests_passes](https://github.com/amadr-95/spring-boot-testing/assets/122611230/bf782de2-a340-4d03-ab2a-83b9a77ad8b5)\n\n## Some test code\n\n- Testing the _PaymentRepository_ class using the settings with `@DataJpaTest`.\n\n```java\n@DataJpaTest //to test JPA queries\nclass PaymentRepositoryTest {\n\n    @Autowired\n    private PaymentRepository underTest;\n\n    @Test\n    void itShouldSavePayment() {\n        //Given\n        long paymentId = 1L;\n        Payment payment = new Payment(paymentId,\n                \"card\",\n                \"donation\",\n                new BigDecimal(10),\n                EUR,\n                UUID.randomUUID());\n\n        //When\n        underTest.save(payment);\n\n        //Then\n        Optional\u003cPayment\u003e optionalPayment = underTest.findById(paymentId);\n        assertThat(optionalPayment)\n                .isPresent()\n                .hasValueSatisfying(\n                        p -\u003e assertThat(p).usingRecursiveComparison().isEqualTo(payment)\n                );\n    }\n}\n```\n\n- Testing the _CustomerService_ class using `@Mock` and `@Captor`.\n\n```java\n@ExtendWith(MockitoExtension.class)\nclass CustomerServiceTest {\n    @Captor\n    private ArgumentCaptor\u003cCustomer\u003e customerArgumentCaptor;\n\n    @Mock\n    private CustomerRepository customerRepository;\n\n    @Mock\n    private PhoneNumberValidator phoneNumberValidator;\n\n    @InjectMocks\n    private CustomerService underTest;\n\n    @Test\n    void itShouldSaveCustomer() throws NumberParseException {\n        //Given\n\n        // .. phoneNumber\n        String phoneNumber = \"600000000\";\n\n        // .. a customer request\n        CustomerRegistrationRequest request = new CustomerRegistrationRequest(\n                \"Amador\", phoneNumber\n        );\n\n        // given a valid number (mock)\n        given(phoneNumberValidator.validate(phoneNumber)).willReturn(true);\n\n        // ... no customer found with that phone number (mock)\n        given(customerRepository.findCustomerByPhoneNumberNative(phoneNumber))\n                .willReturn(Optional.empty());\n\n        //When\n        underTest.registerNewCustomer(request);\n\n        //Then\n        then(customerRepository).should().save(customerArgumentCaptor.capture());\n\n        Customer customer = customerArgumentCaptor.getValue();\n        assertThat(customer).isNotNull();\n        assertThat(customer.getName()).isEqualTo(\"Amador\");\n        assertThat(customer.getPhoneNumber()).isEqualTo(phoneNumber);\n    }\n}\n```\n\n- Testing the _StripeServiceTest_ class mocking static method with Mockito\n\n```java\n@ExtendWith(MockitoExtension.class)\nclass StripeServiceTest {\n\n    @Captor\n    private ArgumentCaptor\u003cPaymentIntentCreateParams\u003e paramsArgumentCaptor;\n\n    @Captor\n    private ArgumentCaptor\u003cRequestOptions\u003e requestOptionsArgumentCaptor;\n\n    private StripeService underTest;\n\n    @BeforeEach\n    public void setUp() {\n        underTest = new StripeService();\n    }\n\n    @Test\n    void itShouldChargeCard() {\n        //Given\n        String method = \"method\";\n        String description = \"description\";\n        BigDecimal amount = new BigDecimal(10);\n        Currency currency = EUR;\n\n        // Mock the PaymentIntent and Charge\n        PaymentIntent paymentIntentMock = mock(PaymentIntent.class);\n        Charge chargeMock = mock(Charge.class);\n\n        // Set up the behavior for the mock objects\n        given(paymentIntentMock.getLatestChargeObject()).willReturn(chargeMock);\n        given(chargeMock.getPaid()).willReturn(true);\n\n\n        try (MockedStatic\u003cPaymentIntent\u003e paymentIntentMockedStatic =\n                     Mockito.mockStatic(PaymentIntent.class)) {\n\n            //Mock the static method call\n            paymentIntentMockedStatic.when(() -\u003e PaymentIntent.create(\n                            any(PaymentIntentCreateParams.class),\n                            any(RequestOptions.class)\n                    )\n            ).thenReturn(paymentIntentMock);\n\n            //When\n            CardPaymentCharge cardPaymentCharge =\n                    underTest.chargeCard(method, amount, currency, description);\n\n            //Then\n            assertThat(cardPaymentCharge).isNotNull();\n            assertThat(cardPaymentCharge.isCardDebited()).isTrue();\n\n            // .. capture the arguments passed to the static method\n            paymentIntentMockedStatic.verify(() -\u003e PaymentIntent.create(\n                    paramsArgumentCaptor.capture(),\n                    requestOptionsArgumentCaptor.capture()\n            ));\n\n            //validate params\n            PaymentIntentCreateParams paramsArgumentCaptorValue = paramsArgumentCaptor.getValue();\n            assertThat(paramsArgumentCaptorValue.getAmount()).isEqualTo(amount.longValue());\n            assertThat(paramsArgumentCaptorValue.getCurrency()).isEqualTo(currency.name().toLowerCase());\n            assertThat(paramsArgumentCaptorValue.getDescription()).isEqualTo(description);\n            assertThat(paramsArgumentCaptorValue.getPaymentMethod()).isEqualTo(method);\n\n            //validate request options\n            RequestOptions requestOptionsArgumentCaptorValue = requestOptionsArgumentCaptor.getValue();\n            assertThat(requestOptionsArgumentCaptorValue.getApiKey()).isEqualTo(\"sk_test_CGGvfNiIPwLXiDwaOfZ3oX6Y\");\n        }\n    }\n}\n```\n\n- Testing the _PaymentIntegrationTest_ class using `@SpringBootTest` and `@AutoConfigureMockMvc` that allows to make\n  HTTP calls to Controllers.\n\n```java\n@SpringBootTest //It starts the application instead of testing separately\n@AutoConfigureMockMvc //Needed to test endpoints\nclass PaymentIntegrationTest {\n\n  @Autowired\n  private CustomerRepository customerRepository;\n  \n  @Autowired\n  private MockMvc mockMvc; //test RESTful API\n\n    @Test\n    void itShouldCreatePaymentSuccessfully() throws Exception {\n        //Given\n\n        // .. a customer request\n        String phoneNumber = \"600000000\";\n        CustomerRegistrationRequest customerRequest = CustomerRegistrationRequest.builder()\n                .name(\"Amador\")\n                .phoneNumber(phoneNumber)\n                .build();\n\n        // a payment request\n        String method = \"method\";\n        String description = \"description\";\n        BigDecimal amount = new BigDecimal(10);\n        Currency currency = EUR;\n        PaymentRequest paymentRequest = PaymentRequest.builder()\n                .paymentMethod(method)\n                .paymentDescription(description)\n                .amount(amount)\n                .currency(currency)\n                .build();\n\n        //When\n        ResultActions resultCustomerRequestActions = mockMvc.perform(post(\"/api/v1/registration\")\n                .contentType(MediaType.APPLICATION_JSON)\n                .content(new ObjectMapper().writeValueAsString(customerRequest)) //json object\n        );\n\n        // get the customerId after insertion in db (client does not send any id)\n        Optional\u003cCustomer\u003e optionalCustomer = customerRepository.findCustomerByPhoneNumberNative(phoneNumber);\n        UUID customerId = null;\n        if (optionalCustomer.isPresent())\n            customerId = optionalCustomer.get().getId();\n\n\n        ResultActions resultPaymentActions = mockMvc.perform(post(\"/api/v1/payment/{customerId}\", customerId)\n                .contentType(MediaType.APPLICATION_JSON)\n                .content(new ObjectMapper().writeValueAsString(paymentRequest))\n        );\n\n        //Then\n        resultCustomerRequestActions.andExpect(status().isOk());\n        resultPaymentActions.andExpect(status().isOk());\n\n        // assertions using get endpoint\n        MvcResult mvcResult = mockMvc.perform(get(\"/api/v1/payment\")).andReturn();\n\n        String jsonResponse = mvcResult.getResponse().getContentAsString();\n\n        List\u003cPayment\u003e payments = new ObjectMapper().readValue(jsonResponse, new TypeReference\u003c\u003e() {\n        });\n\n        assertThat(payments.size()).isEqualTo(1);\n        //get the payment\n        Payment payment = payments.get(0);\n\n        assertThat(payment.getPaymentDescription()).isEqualTo(description);\n        assertThat(payment.getPaymentMethod()).isEqualTo(method);\n        assertThat(payment.getAmount().longValue()).isEqualTo(amount.longValue());\n        assertThat(payment.getCurrency()).isEqualTo(currency);\n        assertThat(payment.getCustomerId()).isEqualTo(customerId);\n    }\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famadr-95%2Fspring-boot-testing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famadr-95%2Fspring-boot-testing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famadr-95%2Fspring-boot-testing/lists"}