Spring MVC REST API için Birim Testleri Yazma: Veri Yazma

In: Genel


Spring MVC Test öğreticimin önceki bölümleri, sistem test edildiğinde Spring MVC REST API için nasıl birim testleri yazabileceğimizi açıkladı. tek bir öğenin bilgilerini döndürür veya bir liste döndürür. Başka bir deyişle, artık verileri JSON olarak döndüren Spring MVC denetleyicileri için nasıl birim testleri yazabileceğimizi biliyoruz.

Bir sonraki adımı atma zamanı. Bu blog gönderisi, istek gövdesinden veri okuyan, geçerli verileri bir veritabanına ekleyen ve verileri JSON olarak döndüren bir Spring MVC REST API uç noktası için nasıl birim testleri yazabileceğimizi açıklar.

Bu blog gönderisini bitirdikten sonra:

  • Nasıl gönderebileceğimizi bilin POST test edilen sisteme yapılan istekler ve HTTP isteğinin istek gövdesini yapılandırın.
  • Doğrulama başarısız olduğunda test edilen sistemin beklendiği gibi çalışmasını nasıl sağlayabileceğimizi anlayın.
  • Doğrulama başarılı olduğunda test edilen sistemin beklendiği gibi çalışmasını nasıl sağlayabileceğimizi bilin.

Hadi başlayalım.

Bu blog yazısı şunları varsayar:

Test Edilen Sisteme Giriş

İşlem yapan bir denetleyici yöntemi için birim testleri yazmalıyız. POST istekler şu yola gönderilir: ‘/todo-item’. Bu API uç noktasının sözleşmesi aşağıda açıklanmıştır:

  • Doğrulama kuralları, Jakarta Bean Validation API kullanılarak belirtilmelidir.
  • Doğrulama başarısız olursa, test edilen sistem HTTP durum kodu 400’ü döndürür.
  • Doğrulama başarısız olursa, test edilen sistem, giriş verilerinden bulunan doğrulama hatalarını açıklayan bir JSON belgesi döndürür.
  • Yeni bir yapılacaklar öğesi başarıyla oluşturulduysa, test edilen sistem HTTP durum kodu 201’i döndürür.
  • Yeni bir yapılacaklar öğesi başarıyla oluşturulduysa, test edilen sistem, oluşturulan yapılacaklar öğesinin bilgilerini içeren bir JSON belgesi döndürür.

Aşağıdaki örnekler, istemciye geri döndürülen JSON belgelerini göstermektedir:

Örnek 1: İstemci, başlığı olmayan yeni bir yapılacaklar öğesi oluşturmaya çalıştı


{
    "fieldErrors":[
        {
            "field":"title",
            "errorCode":"NotBlank"
        }
    ]
}

Örnek 2: Yeni bir yapılacaklar öğesi başarıyla oluşturuldu


{
    "id":1,
    "description":"This is just an example",
    "tags":[],
    "title":"Create a new todo item",
    "status":"OPEN"
}

Test edilen denetleyici yöntemi denir create(). Sadece yeni bir yapılacaklar öğesini veritabanına kaydeder ve oluşturulan yapılacaklar öğesinin bilgilerini döndürür. Test edilen kontrolör yönteminin kaynak kodu aşağıdaki gibidir:


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

@RestController
@RequestMapping("/todo-item")
public class TodoItemCrudController {
    private final TodoItemCrudService service;

    @Autowired
    public TodoItemCrudController(TodoItemCrudService service) {
        this.service = service;
    }
    
    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public TodoItemDTO create(@RequestBody @Valid CreateTodoItemDTO input) {
        return service.create(input);
    }
}

bu CreateTodoItemDTO sınıf, oluşturulan yapılacaklar öğesinin bilgilerini içerir. Ayrıca bu bilgileri doğrulamak için kullanılan doğrulama kurallarını da bildirir. Kaynak kodu şöyle görünür:


import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

public class CreateTodoItemDTO {

    @Size(max = 1000)
    private String description;

    @NotBlank
    @Size(max = 100)
    private String title;

    //Getters and setters are omitted
}

bu TodoItemDTO sınıf, oluşturulan yapılacaklar öğesinin bilgilerini içerir. Kaynak kodu şöyle görünür:


import java.util.List;

public class TodoItemDTO {

    private Long id;
    private String description;
    private List<TagDTO> tags;
    private String title;
    private TodoItemStatus status;

    //Getters and setters are omitted
}

bu TagDTO sınıf, tek bir etiketin bilgisini içerir. Kaynak kodu şöyle görünür:


public class TagDTO {

    private Long id;
    private String name;

    //Getters and setters are omitted
}

bu TodoItemStatus enum, yapılacaklar öğesinin olası durumlarını belirtir. Kaynak kodu şöyle görünür:


public enum TodoItemStatus {
    OPEN,
    IN_PROGRESS,
    DONE
}

Ardından, test edilen sistem tarafından döndürülen yanıt için nasıl iddia yazabileceğimizi öğreneceğiz.

Test Edilen Sistem Tarafından Döndürülen Yanıt için Beyan Yazma

Verileri veritabanına kaydeden ve verileri JSON olarak döndüren bir Spring MVC denetleyicisi için birim testleri yazmadan önce, test edilen sistem tarafından döndürülen HTTP yanıtı için iddiaları nasıl yazabileceğimizi öğrenmeliyiz. Test edilen Spring MVC denetleyicisi tarafından döndürülen HTTP yanıtı için iddialar yazmak istediğimizde, bunları kullanmalıyız. static yöntemleri MockMvcResultMatchers sınıf:

  • bu status() yöntem bir döndürür StatusResultMatchers döndürülen HTTP durumu için iddialar yazmamıza izin veren nesne.
  • bu content() yöntem bir döndürür ContentResultMatchers döndürülen HTTP yanıtının içeriği için iddialar yazmamıza izin veren nesne.
  • bu jsonPath() yöntem bir döndürür JsonPathResultMatchers JsonPath ifadelerini ve Hamcrest eşleştiricilerini kullanarak döndürülen HTTP yanıtının gövdesi için iddialar yazmamıza izin veren nesne.

JsonPath ifadelerini ve Hamcrest eşleştiricilerini kullanarak iddialar yazdığımız için, json-path ve hamcrest-library bağımlılıklar sınıf yolundan bulunur. Maven ve Spring Boot bağımlılık yönetimini kullanıyorsak, aşağıdaki XML parçacığını ekleyerek bu bağımlılıkları bildirebiliriz. dependencies POM dosyamızın bölümü:


<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-library</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <scope>test</scope>
</dependency>

Devam edelim ve gönderen bir istek oluşturucu yöntemini nasıl yazabileceğimizi öğrenelim. POST Test edilen sisteme istekler.

Yeni İstek Oluşturucu Yöntemi Yazma

Test sınıfımızdan yinelenen kodu kaldırmak istediğimiz için, istek oluşturucu sınıfı olarak adlandırılan bir sınıf kullanarak test edilen sisteme HTTP istekleri oluşturmalı ve göndermeliyiz. Başka bir deyişle, test edilen sistem için birim testleri yazmadan önce, test edilen sisteme HTTP istekleri oluşturan ve gönderen bir istek oluşturucu yöntemine yazmamız gerekir. Bu istek oluşturucu yöntemini aşağıdaki adımları izleyerek yazabiliriz:

  1. Ekle private ve static denilen yöntem convertObjectToJsonBytes() istek oluşturucu sınıfımız ve bu yöntemin bir bayt dizisi döndürmesini sağlayın.
  2. emin olun convertObjectToJsonBytes() yöntem alır Object nesneyi bir yöntem parametresi olarak tanımlar ve bu nesneyi bir JSON belgesi içeren bir bayt dizisine dönüştürür.
  3. adlı yeni bir yöntem ekleyin create() istek oluşturucu sınıfımıza. Bu yöntemin bir CreateTodoItemDTO nesneyi bir yöntem parametresi olarak döndürür ve bir ResultActions nesne.
  4. Gönder POST yola istek: ‘/todo-item’ perform() yöntemi MockMvc sınıf. Oluşturulan yapılacaklar öğesinin bilgilerini bir JSON belgesine dönüştürmeyi ve bu bilgileri HTTP isteğinin gövdesine eklemeyi unutmayın.
  5. iade et ResultActions tarafından döndürülen nesne perform() yöntem.

İstek oluşturucu yöntemimizi yazdıktan sonra istek oluşturucu sınıfımızın kaynak kodu aşağıdaki gibi görünür:


import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;

import java.io.IOException;

import static net.petrikainulainen.springmvctest.junit5.web.WebTestConfig.objectMapper;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;

class TodoItemRequestBuilder {

    private final MockMvc mockMvc;

    TodoItemRequestBuilder(MockMvc mockMvc) {
        this.mockMvc = mockMvc;
    }
    
    ResultActions create(CreateTodoItemDTO input) throws Exception {
        return mockMvc.perform(post("/todo-item")
                .contentType(MediaType.APPLICATION_JSON)
                .content(convertObjectToJsonBytes(input))
        );
    }

    private static byte[] convertObjectToJsonBytes(Object object) throws IOException {
        ObjectMapper mapper = objectMapper();
        return mapper.writeValueAsBytes(object);
    }
}

Ardından, test edilen sistem için birim testleri yazmayı öğreneceğiz.

Test Edilen Sistem İçin Birim Testleri Yazma

Test edilen sistem için birim testleri yazmak istediğimizde şu adımları izlemeliyiz:

Öncelikle, gerekli sınıf hiyerarşisini test sınıfımıza eklemeliyiz. Birim testleri yazdığımız için aşağıdaki adımları izleyerek bu sınıf hiyerarşisini oluşturabiliriz:

  1. adlı bir iç sınıf ekleyin Create test sınıfımıza. Bu iç sınıf, test edilen sistemin beklendiği gibi çalışmasını sağlayan test yöntemlerini içerir.
  2. adlı bir iç sınıf ekleyin WhenInvalidInformationIsProvided için Create sınıf. Bu iç sınıf, doğrulama başarısız olduğunda test edilen sistemin beklendiği gibi çalışmasını sağlayan test yöntemlerini içerir.
  3. adlı bir iç sınıf ekleyin WhenFieldValuesAreEmptyStrings için WhenInvalidInformationIsProvided sınıf. Bu iç sınıf, test edilen sistemin beklendiği gibi çalışmasını sağlayan test yöntemlerini içerir. title ve description oluşturulan yapılacaklar öğesinin bir kısmı boş dizelerdir.
  4. adlı bir iç sınıf ekleyin WhenValidInformationIsProvided için Create sınıf. Bu iç sınıf, doğrulama başarılı olduğunda test edilen sistemin beklendiği gibi çalışmasını sağlayan test yöntemlerini içerir.

Test sınıfımıza gerekli sınıf hiyerarşisini ekledikten sonra kaynak kodu şu şekilde görünür:


import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import static net.petrikainulainen.springmvctest.junit5.web.WebTestConfig.*;
import static org.mockito.Mockito.mock;

class TodoItemCrudControllerTest {

    private TodoItemRequestBuilder requestBuilder;
    private TodoItemCrudService service;

    @BeforeEach
    void configureSystemUnderTest() {
        service = mock(TodoItemCrudService.class);

        TodoItemCrudController testedController = new TodoItemCrudController(service);
        MockMvc mockMvc = MockMvcBuilders.standaloneSetup(testedController)
                .setControllerAdvice(new TodoItemErrorHandler())
                .setMessageConverters(objectMapperHttpMessageConverter())
                .build();
        requestBuilder = new TodoItemRequestBuilder(mockMvc);
    }

    @Nested
    @DisplayName("Create a new todo item")
    class Create {

        @Nested
        @DisplayName("When the information of the created todo item isn't valid")
        class WhenInvalidInformationIsProvided {

            @Nested
            @DisplayName("When the field values are empty strings")
            class WhenFieldValuesAreEmptyStrings {

            }
        }

        @Nested
        @DisplayName("When the information of the created todo item is valid")
        class WhenValidInformationIsProvided {

        }
    }
}

İkincieklemeliyiz private input alana Create sınıf. Bu alan şuna bir referans içerir: CreateTodoItemDTO oluşturulan yapılacaklar öğesinin bilgilerini içeren nesne.

Bu alanı ekledikten sonra Create class, test sınıfımızın kaynak kodu aşağıdaki gibi görünüyor:


import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import static net.petrikainulainen.springmvctest.junit5.web.WebTestConfig.*;
import static org.mockito.Mockito.mock;

class TodoItemCrudControllerTest {

    private TodoItemRequestBuilder requestBuilder;
    private TodoItemCrudService service;

    @BeforeEach
    void configureSystemUnderTest() {
        service = mock(TodoItemCrudService.class);

        TodoItemCrudController testedController = new TodoItemCrudController(service);
        MockMvc mockMvc = MockMvcBuilders.standaloneSetup(testedController)
                .setControllerAdvice(new TodoItemErrorHandler())
                .setMessageConverters(objectMapperHttpMessageConverter())
                .build();
        requestBuilder = new TodoItemRequestBuilder(mockMvc);
    }

    @Nested
    @DisplayName("Create a new todo item")
    class Create {

        private CreateTodoItemDTO input;

        @Nested
        @DisplayName("When the information of the created todo item isn't valid")
        class WhenInvalidInformationIsProvided {

            @Nested
            @DisplayName("When the field values are empty strings")
            class WhenFieldValuesAreEmptyStrings {

            }
        }

        @Nested
        @DisplayName("When the information of the created todo item is valid")
        class WhenValidInformationIsProvided {

        }
    }
}

Üçüncüboş olan yeni bir yapılacaklar öğesi oluşturmaya çalıştığımızda test edilen sistemin beklendiği gibi çalıştığından emin olmalıyız. title ve description. Aşağıdaki adımları takip ederek gerekli test yöntemlerini yazabiliriz:

  1. Gerekli sabitleri ekleyin WhenFieldValuesAreEmptyStrings sınıf.
  2. için yeni bir kurulum yöntemi ekleyin. WhenFieldValuesAreEmptyStrings sınıf ve bir test yöntemi çalıştırılmadan önce çalıştırıldığından emin olun. Bu metodu uyguladığımızda yeni bir tane oluşturmalıyız. CreateTodoItemDTO boş olan nesne title ve descriptionve oluşturulan nesneyi input alan.
  3. Test edilen sistemin 400 HTTP durum kodunu döndürdüğünden emin olun.
  4. Test edilen sistemin doğrulama hatalarını JSON olarak döndürdüğünü doğrulayın.
  5. Test edilen sistemin bir doğrulama hatası döndürdüğünden emin olun.
  6. Test edilen sistemin boş bir başlık hakkında bir doğrulama hatası döndürdüğünü doğrulayın.
  7. Test edilen sistemin yeni bir yapılacaklar öğesi oluşturmadığından emin olun.

Gerekli test yöntemlerini yazdıktan sonra test sınıfımızın kaynak kodu şu şekilde görünüyor:


import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import static net.petrikainulainen.springmvctest.junit5.web.WebTestConfig.*;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.hasSize;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

class TodoItemCrudControllerTest {

    private TodoItemRequestBuilder requestBuilder;
    private TodoItemCrudService service;

    @BeforeEach
    void configureSystemUnderTest() {
        service = mock(TodoItemCrudService.class);

        TodoItemCrudController testedController = new TodoItemCrudController(service);
        MockMvc mockMvc = MockMvcBuilders.standaloneSetup(testedController)
                .setControllerAdvice(new TodoItemErrorHandler())
                .setMessageConverters(objectMapperHttpMessageConverter())
                .build();
        requestBuilder = new TodoItemRequestBuilder(mockMvc);
    }

    @Nested
    @DisplayName("Create a new todo item")
    class Create {

        private CreateTodoItemDTO input;

        @Nested
        @DisplayName("When the information of the created todo item isn't valid")
        class WhenInvalidInformationIsProvided {

            @Nested
            @DisplayName("When the field values are empty strings")
            class WhenFieldValuesAreEmptyStrings {

                private static final String VALIDATION_ERROR_EMPTY_VALUE = "NotBlank";

                @BeforeEach
                void createInputWithEmptyFieldValues() {
                    input = new CreateTodoItemDTO();
                    input.setDescription("");
                    input.setTitle("");
                }

                @Test
                @DisplayName("Should return the HTTP status code bad request (400)")
                void shouldReturnHttpStatusCodeBadRequest() throws Exception {
                    requestBuilder.create(input)
                            .andExpect(status().isBadRequest());
                }

                @Test
                @DisplayName("Should return validation errors as JSON")
                void shouldReturnValidationErrorsAsJson() throws Exception {
                    requestBuilder.create(input)
                            .andExpect(
                                    content().contentType(MediaType.APPLICATION_JSON)
                            );
                }

                @Test
                @DisplayName("Should return one validation error")
                void shouldReturnOneValidationError() throws Exception {
                    requestBuilder.create(input)
                            .andExpect(jsonPath("$.fieldErrors", hasSize(1)));
                }

                @Test
                @DisplayName("Should return a validation error about empty title")
                void shouldReturnValidationErrorAboutEmptyTitle() throws Exception {
                    requestBuilder.create(input)
                            .andExpect(jsonPath(
                                    "$.fieldErrors[?(@.field == 'title')].errorCode",
                                    contains(VALIDATION_ERROR_EMPTY_VALUE)
                            ));
                }

                @Test
                @DisplayName("Shouldn't create a new todo item")
                void shouldNotCreateNewTodoItem() throws Exception {
                    requestBuilder.create(input);

                    verify(service, never()).create(any());
                }
            }
        }

        //The other inner class is omitted
    }
}
Doğrulama şu durumlarda başarısız olur:

  • Oluşturulan yapılacaklar öğesinin başlığı null
  • Oluşturulan yapılacaklar öğesinin başlığı boş.
  • Oluşturulan yapılacaklar öğesinin başlığı yalnızca boşluk karakterlerini içerir.
  • Oluşturulan yapılacaklar öğesinin başlığı veya açıklaması çok uzun.

Bu blog yazısı sadece bir senaryoyu kapsıyor çünkü kendimi tekrarlamak istemedim. Test edilen sistemin tüm olası senaryolarda beklendiği gibi çalışmasını sağlayan testlere göz atmak isterseniz, bu blog gönderisinin örnek uygulamasına bir göz atın.

Dördüncü, doğrulama başarılı olduğunda test edilen sistemin beklendiği gibi çalıştığından emin olmalıyız. Aşağıdaki adımları takip ederek gerekli test yöntemlerini yazabiliriz:

  1. Gerekli sabitleri ekleyin WhenValidInformationIsProvided sınıf.
  2. için yeni bir kurulum yöntemi ekleyin. WhenValidInformationIsProvided sınıf ve bir test yöntemi çalıştırılmadan önce çalıştırıldığından emin olun. Bu yöntemi uyguladığımızda şunları yapmalıyız:
    • Yeni bir tane oluştur CreateTodoItemDTO geçerli nesne title ve description. Bu nesneyi oluşturduktan sonra, onu input alan.
    • emin olun create() yöntemi TodoItemCrudService class, oluşturulan yapılacaklar öğesinin bilgilerini döndürür.
  3. Test edilen sistemin 201 HTTP durum kodunu döndürdüğünden emin olun.
  4. Test edilen sistemin, oluşturulan yapılacaklar öğesinin bilgilerini JSON olarak döndürdüğünü doğrulayın.
  5. Test edilen sistemin, oluşturulan yapılacaklar öğesinin bilgilerini döndürdüğünden emin olun.
  6. Test edilen sistemin doğru açıklamaya sahip yeni bir yapılacaklar öğesi oluşturduğunu doğrulayın.
  7. Test edilen sistemin doğru başlığa sahip yeni bir yapılacaklar öğesi oluşturduğundan emin olun.

Gerekli test yöntemlerini yazdıktan sonra test sınıfımızın kaynak kodu şu şekilde görünüyor:


import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import java.util.ArrayList;

import static info.solidsoft.mockito.java8.AssertionMatcher.assertArg;
import static net.petrikainulainen.springmvctest.junit5.web.WebTestConfig.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

class TodoItemCrudControllerTest {

    private TodoItemRequestBuilder requestBuilder;
    private TodoItemCrudService service;

    @BeforeEach
    void configureSystemUnderTest() {
        service = mock(TodoItemCrudService.class);

        TodoItemCrudController testedController = new TodoItemCrudController(service);
        MockMvc mockMvc = MockMvcBuilders.standaloneSetup(testedController)
                .setControllerAdvice(new TodoItemErrorHandler())
                .setMessageConverters(objectMapperHttpMessageConverter())
                .build();
        requestBuilder = new TodoItemRequestBuilder(mockMvc);
    }

    @Nested
    @DisplayName("Create a new todo item")
    class Create {

        private CreateTodoItemDTO input;

        //The other inner class is omitted

        @Nested
        @DisplayName("When the information of the created todo item is valid")
        class WhenValidInformationIsProvided {

            private static final int MAX_LENGTH_DESCRIPTION = 1000;
            private static final int MAX_LENGTH_TITLE = 100;

            private static final String DESCRIPTION = WebTestUtil
                    .createStringWithLength(MAX_LENGTH_DESCRIPTION);
            private static final Long ID = 1L;
            private static final String TITLE = WebTestUtil
                    .createStringWithLength(MAX_LENGTH_TITLE);

            @BeforeEach
            void configureSystemUnderTest() {
                input = createInputWithValidInformation();
                returnCreatedTodoItem();
            }

            private CreateTodoItemDTO createInputWithValidInformation() {
                CreateTodoItemDTO input = new CreateTodoItemDTO();
                input.setDescription(DESCRIPTION);
                input.setTitle(TITLE);
                return input;
            }

            private void returnCreatedTodoItem() {
                TodoItemDTO created = new TodoItemDTO();
                created.setId(ID);
                created.setDescription(DESCRIPTION);
                created.setStatus(TodoItemStatus.OPEN);
                created.setTags(new ArrayList<>());
                created.setTitle(TITLE);

                given(service.create(any())).willReturn(created);
            }

            @Test
            @DisplayName("Should return the HTTP status status code created (201)")
            void shouldReturnHttpStatusCodeCreated() throws Exception {
                requestBuilder.create(input)
                        .andExpect(status().isCreated());
            }

            @Test
            @DisplayName("Should return the information of the created todo item as JSON")
            void shouldReturnInformationOfCreatedTodoItemAsJSON() throws Exception {
                requestBuilder.create(input)
                        .andExpect(content().contentType(MediaType.APPLICATION_JSON));
            }

            @Test
            @DisplayName("Should return the information of the created todo item")
            void shouldReturnInformationOfCreatedTodoItem() throws Exception {
                requestBuilder.create(input)
                        .andExpect(jsonPath("$.id", equalTo(ID.intValue())))
                        .andExpect(jsonPath("$.description", equalTo(DESCRIPTION)))
                        .andExpect(jsonPath("$.status", 
                                equalTo(TodoItemStatus.OPEN.name())
                        ))
                        .andExpect(jsonPath("$.tags", hasSize(0)))
                        .andExpect(jsonPath("$.title", equalTo(TITLE)));
            }

            @Test
            @DisplayName("Should create a new todo item with the correct description")
            void shouldCreateNewTodoItemWithCorrectDescription() throws Exception {
                requestBuilder.create(input);
                verify(service, times(1)).create(assertArg(
                        created -> assertThat(created.getDescription())
                                .isEqualTo(DESCRIPTION)
                ));
            }

            @Test
            @DisplayName("Should create a new todo item with the correct title")
            void shouldCreateNewTodoItemWithCorrectTitle() throws Exception {
                requestBuilder.create(input);
                verify(service, times(1)).create(assertArg(
                        created -> assertThat(created.getTitle())
                                .isEqualTo(TITLE)
                ));
            }
        }
    }
}

Artık veri tabanına veri ekleyen ve veriyi JSON olarak döndüren bir Spring MVC REST API uç noktası için birim testleri yazabiliriz. Bu blog gönderisinden öğrendiklerimizi özetleyelim.

Özet

Bu blog yazısı bize dört şey öğretti:

  • Döndürülen HTTP durumu için iddialar yazmak istediğimizde, şunu çağırmamız gerekir: status() yöntemi MockMvcResultMatchers sınıf.
  • Döndürülen HTTP yanıtının içeriği için iddialar yazmak istediğimizde, şunu çağırmamız gerekir: content() yöntemi MockMvcResultMatchers sınıf.
  • JsonPath ifadelerini ve Hamcrest eşleştiricilerini kullanarak döndürülen HTTP yanıtının gövdesi için iddialar yazmak istediğimizde, şunu çağırmamız gerekir: jsonPath() yöntemi MockMvcResultMatchers sınıf.
  • JsonPath ifadelerini ve Hamcrest eşleştiricilerini kullanarak döndürülen HTTP yanıtının gövdesi için iddialar yazmak istiyorsak, json-path ve hamcrest-library bağımlılıklar sınıf yolundan bulunur

Not: Yapabilirsiniz bu blog gönderisinin örnek uygulamasını Github’dan alın.

Bir cevap yazın

Ready to Grow Your Business?

We Serve our Clients’ Best Interests with the Best Marketing Solutions. Find out More

How Can We Help You?

Need to bounce off ideas for an upcoming project or digital campaign? Looking to transform your business with the implementation of full potential digital marketing?

For any career inquiries, please visit our careers page here.
[contact-form-7 404 "Bulunamadı"]