Monday, December 8, 2025

Spring Boot Unit Tests Explanation Guide with full code

 

Spring Boot Unit Tests Explanation Guide with full code

Spring Boot Unit Tests Explanation Guide with full code


✅ 1. Spring Boot Unit Tests

Create folder:

src/test/java/com/example/profitloss/

Test 1 — Service Logic Test (CalculationServiceTest.java)

package com.example.profitloss;

import com.example.profitloss.model.
Calculation;
import com.example.profitloss.repo.
CalculationRepository;
import com.example.profitloss.service.
CalculationService;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.junit.jupiter.
api.Assertions.*;

public class CalculationServiceTest {

    private final CalculationRepository
 repo = Mockito.mock(CalculationRepository.
class);
    private final CalculationService 
service = new CalculationService(repo);

    @Test
    void testProfit() {
        double cp = 500;
        double sp = 650;

        Calculation saved = new 
Calculation(cp, sp, 150, 30, true);
        Mockito.when(repo.save
(Mockito.any())).thenReturn(saved);

        Calculation calc = service.
calculateAndSave(cp, sp);

        assertEquals(150, calc.getAmount());
        assertEquals(30, calc.getPercent());
        assertTrue(calc.isProfit());
    }

    @Test
    void testLoss() {
        double cp = 500;
        double sp = 300;

        Calculation saved = new 
Calculation(cp, sp, 200, 40, false);
        Mockito.when(repo.save
(Mockito.any())).thenReturn(saved);

        Calculation calc = service.
calculateAndSave(cp, sp);

        assertEquals(200, calc.getAmount());
        assertEquals(40, calc.getPercent());
        assertFalse(calc.isProfit());
    }

    @Test
    void testNoProfitNoLoss() {
        double cp = 500;
        double sp = 500;

        Calculation saved =
 new Calculation(cp, sp, 0, 0, false);
        Mockito.when(repo.save
(Mockito.any())).thenReturn(saved);

        Calculation calc = service.
calculateAndSave(cp, sp);

        assertEquals(0, calc.getAmount());
        assertEquals(0, calc.getPercent());
    }
}

Test 2 — REST API Test Using MockMVC (CalculationControllerTest.java)

package com.example.profitloss;

import com.example.profitloss.
controller.CalculationController;
import com.example.profitloss.
dto.CalculateRequest;
import com.example.profitloss.
model.Calculation;
import com.example.profitloss.
service.CalculationService;

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.
beans.factory.annotation.Autowired;
import org.springframework.
boot.test.autoconfigure.web.
servlet.WebMvcTest;
import org.springframework.
boot.test.mock.mockito.MockBean;
import org.springframework.
http.MediaType;
import org.springframework.
test.web.servlet.MockMvc;

import static org.springframework.
test.web.servlet.request.
MockMvcRequestBuilders.post;
import static org.springframework.
test.web.servlet.result.
MockMvcResultMatchers.*;

@WebMvcTest(CalculationController.class)
public class CalculationControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private CalculationService 
calculationService;

    @Test
    void testPostCalculate() 
throws Exception {
        Calculation mockSave =
 new Calculation(500, 650, 150, 30, true);
        mockSave.setId(1L);

        Mockito.when(calculationService.
calculateAndSave(500, 650))
                .thenReturn(mockSave);

        mockMvc.perform(
                post("/api/calculate")
                    .contentType
(MediaType.APPLICATION_JSON)
                    .content
("{\"cp\":500,\"sp\":650}")
        )
        .andExpect(status().isOk())
        .andExpect(jsonPath("$.type")
.value("profit"))
        .andExpect(jsonPath("$.amount")
.value(150.0))
        .andExpect(jsonPath("$.percent")
.value(30.0))
        .andExpect(jsonPath("$.id")
.value(1));
    }
}

✅ 2. Retrofit Integration (Android Kotlin)

Integrate your Android app with the REST API running on Spring Boot.

Step 1: Add Retrofit dependency

In app/build.gradle:

implementation("com.squareup.
retrofit2:retrofit:2.9.0")
implementation("com.squareup.
retrofit2:converter-gson:2.9.0")

Step 2: Create Data Models

CalculateRequest.kt

data class CalculateRequest(
    val cp: Double,
    val sp: Double
)

CalculateResponse.kt

data class CalculateResponse(
    val type: String,
    val amount: Double,
    val percent: Double,
    val id: Long
)

Step 3: Retrofit API Interface

ProfitLossApi.kt

import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.POST

interface ProfitLossApi {
    @POST("/api/calculate")
    fun calculate(@Body req: 
CalculateRequest): Call<CalculateResponse>
}

Step 4: Retrofit Client

RetrofitClient.kt

import retrofit2.Retrofit
import retrofit2.converter.
gson.GsonConverterFactory

object RetrofitClient {
    val instance: ProfitLossApi by lazy {
        Retrofit.Builder()
            .baseUrl("http://10.0.2.2:8080")
 // Android emulator → localhost
            .addConverterFactory
(GsonConverterFactory.create())
            .build()
            .create(ProfitLossApi:
:class.java)
    }
}

Step 5: Call the API from MainActivity

RetrofitClient.instance.calculate
(CalculateRequest(cp, sp))
    .enqueue(object : retrofit2.
Callback<CalculateResponse> {
        override fun onResponse(
            call: retrofit2.Call<
CalculateResponse>,
            response: retrofit2.
Response<CalculateResponse>
        ) {
            val body = response.body()
            if (body != null) {
                tvResult.text = """
                    Type: ${body.type}
                    Amount: ${body.amount}
                    Percent: ${body.percent}
                    Saved ID: ${body.id}
                """.trimIndent()
            }
        }

        override fun onFailure(call:
 retrofit2.Call<CalculateResponse>,
 t: Throwable) {
            tvResult.text = "Error: 
${t.message}"
        }
    })

✅ 3. Postman Collection (Export JSON)

Copy and paste into a .json file and import into Postman.

profitloss.postman_collection.json

{
  "info": {
    "name": "Profit Loss API",
    "_postman_id": "a1b2c3d4",
    "schema": "https://schema.
getpostman.com/json/collection/v2.1.0/
collection.json"
  },
  "item": [
    {
      "name": "Calculate Profit or Loss",
      "request": {
        "method": "POST",
        "header": [{"key": "Content-Type",
 "value": "application/json"}],
        "body": {
          "mode": "raw",
          "raw": "{\"cp\":500,\"sp\":650}"
        },
        "url": "http://localhost:
8080/api/calculate"
      }
    },
    {
      "name": "Get Saved Calculation",
      "request": {
        "method": "GET",
        "url": "http://localhost:
8080/api/calculation/1"
      }
    }
  ]
}

✅ 4. OpenAPI / Swagger Specification (openapi.yaml)

openapi: 3.0.1
info:
  title: Profit & Loss API
  version: 1.0.0

paths:
  /api/calculate:
    post:
      summary: Calculate and save profit/loss
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                cp:
                  type: number
                sp:
                  type: number
      responses:
        "200":
          description: Calculation result
          content:
            application/json:
              schema:
                type: object
                properties:
                  type:
                    type: string
                  amount:
                    type: number
                  percent:
                    type: number
                  id:
                    type: integer

  /api/calculation/{id}:
    get:
      summary: Get saved calculation by ID
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: Calculation found
        "404":
          description: Not found

If you include SpringDoc OpenAPI UI, you get Swagger UI automatically:

Add to pom.xml:

<dependency>
  <groupId>org.springdoc</groupId>
  <artifactId>springdoc-openapi-
starter-webmvc-ui</artifactId>
  <version>2.2.0</version>
</dependency>

Then open:

👉 http://localhost:8080/swagger-ui.html

🎉 All items completed!

You now have:

✔ Unit Tests
✔ Retrofit Android integration
✔ Postman Collection
✔ OpenAPI/Swagger Spec

BEST OF LUCK ...

The Definitive Guide to Bootstrap CSS Buttons Reference: Styling, Sizing, and State Management

  The Definitive Guide to Bootstrap CSS Buttons Reference: Styling, Sizing, and State Management Buttons drive user actions in web apps. Th...