Posted on: December 24, 2021 Posted by: rahulgite Comments: 12

Create a new controller and hello service

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String helloWorld(){
        return "Hello World";
    }
}

JUnit 4 Code

@RunWith(SpringRunner.class)

@WebMvcTest(HelloWorldController.class)

JUnit 5 Code

@WebMvcTest(HelloWorldController.class)

 

Testing Simple Hello Controller

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import static org.junit.jupiter.api.Assertions.*;

@WebMvcTest(HelloController.class)
class HelloControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Test
    void helloWorld() throws Exception {
        // request GET /hello and application/json
        RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/hello")
                .accept(MediaType.APPLICATION_JSON);

        MvcResult result=mockMvc.perform(requestBuilder).andReturn();

        //verify controller
        assertEquals("Hello World",result.getResponse().getContentAsString());
    }
}

Controller with status and content

    @Test
    void helloWorldWithContentAndStatus() throws Exception {
        // request GET /hello and application/json
        RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/hello")
                .accept(MediaType.APPLICATION_JSON);

        MvcResult result=mockMvc.perform(requestBuilder)
                .andExpect(status().isOk())
                .andExpect(MockMvcResultMatchers.content().string("Hello World"))
                .andReturn();

    }

Controller with JSON Response

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(ObjectController.class)
class ObjectControllerTest {
    @Autowired
    private MockMvc mockMvc;
@Test
    void objReturnTest() throws Exception {
        RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/get-item")
                .accept(MediaType.APPLICATION_JSON);

        MvcResult result=mockMvc.perform(requestBuilder)
                .andExpect(status().isOk())
                .andExpect(MockMvcResultMatchers.content().json("{\"id\":1,\"name\":\"Ball\"}"))
                .andReturn();
    }
}

JSON Assert 

// JSON response should be exact may have space.
@Test
void jsonAssertionStrictTrueExceptSpaces() throws Exception {
    String actualJson = "{\"id\":1,\"name\":\"Ball\"}";
    String expectedJson = "{\"id\":1,\"name\":\"Ball\"}";

    JSONAssert.assertEquals(expectedJson, actualJson,true);
}

// JSON response should contain may have space.
@Test
void jsonAssertionStrictFalseExceptSpaces() throws Exception {
    String actualJson = "{\"id\":1,\"name\":\"Ball\",\"age\":33}";
    String expectedJson = "{\"id\":1,\"name\":\"Ball\"}";

    JSONAssert.assertEquals(expectedJson, actualJson,false);
}

// JSON response can be written without escape character if value does not contain spaces
@Test
void jsonAssertionWithoutEscapeCharacter() throws Exception {
    String actualJson = "{id:1,name:Ball,age:33}";
    String expectedJson = "{id:1,name:Ball}";

    JSONAssert.assertEquals(expectedJson, actualJson,false);
}

Testing Controller invoking Business Layer

@MockBean
BusinessService businessService;
@Test
void objReturnFromBusiness() throws Exception {
    when(businessService.getData()).thenReturn(new Item(1,"Ball"));
    RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/get-business-item")
            .accept(MediaType.APPLICATION_JSON);

    MvcResult result = mockMvc.perform(requestBuilder)
            .andExpect(status().isOk())
            .andExpect(MockMvcResultMatchers.content().json("{id:1,name:Ball}"))
            .andReturn();
}
UPDATE : H2 Database URL

With the latest versions of Spring Boot (2.3+), the H2 database name is randomly generated each time you restart the server.

You can find the database name and URL from the console log.

RECOMMENDED:

Make the database URL a constant by configuring this in application.properties.

spring.datasource.url=jdbc:h2:mem:testdb
spring.data.jpa.repositories.bootstrap-mode=default

Business Layer Test

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;

import java.util.Arrays;
import java.util.List;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import com.in28minutes.unittesting.unittesting.data.ItemRepository;
import com.in28minutes.unittesting.unittesting.model.Item;

@ExtendWith(MockitoExtension.class)
public class ItemBusinessServiceTest {

    @InjectMocks
    private ItemBusinessService business;

    @Mock
    private ItemRepository repository;

    @Test
    public void retrieveAllItems_basic() {
        when(repository.findAll()).thenReturn(Arrays.asList(new Item(2,"Item2",10,10),
                new Item(3,"Item3",20,20)));
        List<Item> items = business.retrieveAllItems();
        
        assertEquals(100, items.get(0).getValue());
        assertEquals(400, items.get(1).getValue());
    }
}

Repository Test

JUnit 4 Code

@RunWith(SpringRunner.class)

@DataJpaTest

JUnit 5 Code

@DataJpaTest

import org.json.JSONException;
import org.junit.jupiter.api.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;

@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class ItemControllerIT {
    
    @Autowired
    private TestRestTemplate restTemplate;
        
    @Test
    public void contextLoads() throws JSONException {	
        
        String response = this.restTemplate.getForObject("/all-items-from-database", String.class);
        
        JSONAssert.assertEquals("[{id:10001},{id:10002},{id:10003}]", 
                response, false);
    }

}

Integration Test

JUnit 4 Code

@RunWith(SpringRunner.class)

@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)

JUnit 5 Code

@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)

import org.json.JSONException;
import org.junit.jupiter.api.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;

@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class ItemControllerIT {
    
    @Autowired
    private TestRestTemplate restTemplate;
        
    @Test
    public void contextLoads() throws JSONException {	
        
        String response = this.restTemplate.getForObject("/all-items-from-database", String.class);
        
        JSONAssert.assertEquals("[{id:10001},{id:10002},{id:10003}]", 
                response, false);
    }

}

Use Specific Application properties for TestCases

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
@TestPropertySource(locations= {"classpath:test-configuration.properties"})  //High priority and override any other config
public class UnitTestingApplicationTests {

    @Test
    public void contextLoads() {
    }
}

else create test>resources>application.properties

 

Hamcrest Matchers Tests

import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;

class ItemRepositoryTest {

    @Test
    void hamcrestTest() {
        List<Integer> no = Arrays.asList(1, 2, 3, 4);
        assertThat(no, hasSize(4));
        assertThat(no, hasItems(1, 2));
        assertThat(no, everyItem(greaterThan(0)));
        assertThat(no, everyItem(lessThan(100)));
        assertThat("", isEmptyString());
        assertThat("ABCDE", containsString("AB"));
        assertThat("ABCDE", startsWith("AB"));
        assertThat("ABCDE", endsWith("DE"));
    }
}

AssertJ Tests

import static org.assertj.core.api.Assertions.assertThat;

import java.util.Arrays;
import java.util.List;

import org.junit.jupiter.api.Test;

public class AssertJTest {
    
    @Test
    public void learning() {
        List<Integer> numbers = Arrays.asList(12,15,45);
        
        //assertThat(numbers, hasSize(3));
        assertThat(numbers).hasSize(3)
                        .contains(12,15)
                        .allMatch(x -> x > 10)
                        .allMatch(x -> x < 100)
                        .noneMatch(x -> x < 0);
        
        assertThat("").isEmpty();
        assertThat("ABCDE").contains("BCD")
                        .startsWith("ABC")
                        .endsWith("CDE");		
    }

}

JSONPathTest

import static org.assertj.core.api.Assertions.assertThat;

import java.util.List;

import org.junit.jupiter.api.Test;

import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;

public class JsonPathTest {
    
    @Test
    public void learning() {
        String responseFromService = "[" + 
                "{\"id\":10000, \"name\":\"Pencil\", \"quantity\":5}," + 
                "{\"id\":10001, \"name\":\"Pen\", \"quantity\":15}," + 
                "{\"id\":10002, \"name\":\"Eraser\", \"quantity\":10}" + 
                "]";
        
        DocumentContext context = JsonPath.parse(responseFromService);
        
        int length = context.read("$.length()");
        assertThat(length).isEqualTo(3);
        
        List<Integer> ids = context.read("$..id");

        assertThat(ids).containsExactly(10000,10001,10002);
        
        System.out.println(context.read("$.[1]").toString());
        System.out.println(context.read("$.[0:2]").toString());
        System.out.println(context.read("$.[?(@.name=='Eraser')]").toString());
        System.out.println(context.read("$.[?(@.quantity==5)]").toString());	
    }
}

What are good TestCases

  1. The test should be readable
  2. The test should be fast.
  3. The test should be Isolated – fails only when issue with code.
  4. The test should be run often.

 

Website for Reference: http://xunitpatterns.com/

Loading

12 People reacted on this

  1. I’ve been surfing online more than three hours today, yet I never found any interesting article like yours.

    It is pretty worth enough for me. Personally, if all site owners and bloggers made good content as you
    did, the internet will be much more useful than ever before.

Leave a Comment