Spring MVC REST API için Birim Testleri Yazma: Yapılandırma

In: Genel


Daha önce öğrendik Spring MVC denetleyicileri için birim testleri yazarken bağımsız yapılandırmayı kullanarak test edilen sistemi yapılandırmamız gerektiğini.

Bu blog yazısında teoriyi pratiğe dökeceğiz. Bu blog gönderisi, bir REST API uygulayan Spring MVC denetleyicileri için birim testleri yazarken bağımsız yapılandırmayı nasıl kullanabileceğimizi açıklar.

Bu blog gönderisini bitirdikten sonra:

  • Test takımımıza yinelenen kod eklemeden gerekli bileşenleri nasıl oluşturup yapılandırabileceğimizi anlayın.
  • Test takımımıza yinelenen kod eklemeden test edilen sisteme HTTP isteklerini nasıl gönderebileceğimizi öğrenin.
  • JUnit 5 ile bir Spring MVC REST API için birim testleri yazarken Spring MVC Test çerçevesini yapılandırabilir.

Hadi başlayalım.

Bu blog yazısı şunları varsayar:

Test Edilen Sisteme Giriş

Test edilen sistem iki sınıftan oluşur:

  • bu TodoItemCrudController sınıfı, yapılacaklar öğeleri için CRUD işlemleri sağlayan bir REST API uygulayan denetleyici yöntemlerini içerir.
  • bu TodoItemCrudService sınıf, yapılacaklar öğeleri için CRUD işlemleri sağlar. bu TodoItemCrudController class, HTTP isteklerini işlerken yöntemlerini çağırır.

İlgili kısım TodoItemCrudController sınıf aşağıdaki gibi görünür:


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/todo-item")
public class TodoItemCrudController {

    private final TodoItemCrudService service;

    @Autowired
    public TodoItemCrudController(TodoItemCrudService service) {
        this.service = service;
    }
}

Ardından, bağımsız yapılandırmayı kullanarak test edilen sistemi yapılandırdığımızda oluşturulan minimum Spring MVC yapılandırmasını genişleten bileşenleri oluşturacağız.

Gerekli Bileşenleri Oluşturma

hatırladığımız gibi, test edilen sisteme dahil ettiğimiz özel bileşenlerin sayısını en aza indirmeliyiz. Bununla birlikte, çok fazla deneyime sahip değilsek, temel bileşenleri belirlemek zor olabilir. Bu yüzden gerekli bileşenleri seçmemize yardımcı olacak iki kural yazdım:

  • Bir özel oluşturmalı ve yapılandırmalıyız HttpMessageConverter bir özel kullanmak istiyorsak ObjectMapper bu, JSON’u nesnelere dönüştürür ve bunun tersi de geçerlidir.
  • Eğer bir Locale nesne, test edilen denetleyicinin bir yöntemine bir yöntem parametresi olarak enjekte edilirse, bir özel oluşturmalı ve yapılandırmalıyız. LocaleResolver.
Belirtmek istediğim iki şey var:

  • özel kullanırsak ObjectMapperyapılandırılmış bir sonuç döndüren bir fabrika yöntemi yazmalıyız. ObjectMapper nesne. Bu, test edilen sisteme JSON belgelerini gönderen testler yazmamıza yardımcı olur. Ayrıca bu, test yöntemlerimizin ve Spring MVC Test çerçevesinin aynı konfigürasyonu kullanmasını sağlar.
  • Özel bir yapılandırma yapmıyoruz LocaleResolver çünkü denetleyicimiz onu kullanmıyor. Ancak, ihtiyacınız varsa, kullanmalısınız. FixedLocaleResolver sınıf.

Aşağıdaki adımları izleyerek gerekli bileşenleri oluşturabilir ve yapılandırabiliriz:

Önceliklebir tane oluşturmalıyız public Gerekli bileşenleri oluşturan ve yapılandıran fabrika yöntemlerini içeren nesne ana sınıfı. Ana sınıf nesnemizi oluşturduktan sonra, kimsenin onu somutlaştıramayacağından emin olmalıyız.

Nesne ana sınıfımızı oluşturduktan sonra kaynak kodu şu şekilde görünür:


public final class WebTestConfig {
 
    private WebTestConfig() {}
}
Belirtmek istediğim iki şey var:

  • Test sınıflarımızı nesne ana sınıfımızla aynı pakete koymak istemediğimiz için nesne ana sınıfımız olmalıdır. public. Ayrıca bu, nesne ana sınıfımıza eklenen tüm fabrika yöntemlerinin olması gerektiği anlamına gelir. public ilave olarak.
  • Bir nesne ana sınıfı kullanmalıyız çünkü birden çok test sınıfı aynı bileşenleri kullanır ve test takımımıza yinelenen kod eklemek istemiyoruz.

İkincieklemeliyiz public ve static denilen yöntem objectMapper() nesne ana sınıfımıza. Bu yöntem, yeni bir ObjectMapper nesne ve oluşturulan nesneyi döndürür. Testlerimiz, test edilen sisteme gönderilen JSON belgelerini oluştururken bu yöntemi kullanacaktır.

Bu metodu yazdıktan sonra nesne ana sınıfımızın kaynak kodu şu şekilde görünür:


import com.fasterxml.jackson.databind.ObjectMapper;

public final class WebTestConfig {
    
    private WebTestConfig() {}
    
    public static ObjectMapper objectMapper() {
        return new ObjectMapper();
    }
}

Üçüncüeklemeliyiz public ve static denilen yöntem objectMapperHttpMessageConverter() nesne ana sınıfımıza. Test sınıflarımız, test edilen sistemi yapılandırırken bu yöntemi kullanacaklardır. Bu metodu nesne ana sınıfımıza ekledikten sonra şu adımları takip ederek uygulamamız gerekiyor:

  1. Yeni oluşturmak MappingJackson2HttpMessageConverter nesne. Bu nesne, Jackson kullanarak JSON okuyabilir ve yazabilir.
  2. yapılandırın ObjectMapper oluşturulan tarafından kullanılan MappingJackson2HttpMessageConverter nesne.
  3. Oluşturulan nesneyi döndürün.

Bu yöntemi uyguladıktan sonra, nesne ana 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.converter.json.MappingJackson2HttpMessageConverter;

public final class WebTestConfig {

    private WebTestConfig() {}

    public static MappingJackson2HttpMessageConverter objectMapperHttpMessageConverter() {
        MappingJackson2HttpMessageConverter converter = 
                new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(objectMapper());
        return converter;
    }

    public static ObjectMapper objectMapper() {
        return new ObjectMapper();
    }
}

Artık bir nesne ana sınıfı kullanarak gerekli bileşenleri oluşturabiliriz. Devam edelim ve test edilen sisteme HTTP istekleri gönderen bir istek oluşturucu sınıfını nasıl oluşturabileceğimizi öğrenelim.

İstek Oluşturucu Sınıfını Oluşturma

Gerçek hayattaki bir web uygulaması veya bir REST API için birim testleri yazdığımızda, her test yönteminin yeni bir HTTP isteği oluşturduğunu ve test edilen sisteme gönderdiğini fark ederiz. Bu kötü bir durum çünkü yinelenen kod, testlerimizi yazmayı ve sürdürmeyi zorlaştırıyor.

Bu sorunu request oluşturucu sınıflarını kullanarak çözebiliriz. İstek oluşturucu sınıfı, şu koşulları karşılayan bir sınıftır:

  • kullanarak test edilen sisteme HTTP istekleri oluşturan ve gönderen yöntemleri içerir. MockMvc nesne.
  • Her yöntem bir döndürmelidir ResultActions döndürülen HTTP yanıtı için iddialar yazmamıza izin veren nesne.

Aşağıdaki adımları takip ederek request builder sınıfımızı yazabiliriz:

  1. Yeni bir sınıf oluşturun.
  2. Ekle private MockMvc oluşturulan sınıfa alan. İstek oluşturucu sınıfımız, test edilen sisteme HTTP istekleri oluştururken ve gönderirken bu alanı kullanacaktır.
  3. Kullanılmış olanı enjekte edebildiğimizden emin olun MockMvc içine nesne mockMvc yapıcı enjeksiyon kullanarak alan.

İstek oluşturucu sınıfımızı oluşturduktan sonra kaynak kodu şu şekilde görünür:


import org.springframework.test.web.servlet.MockMvc;

class TodoItemRequestBuilder {

    private final MockMvc mockMvc;

    TodoItemRequestBuilder(MockMvc mockMvc) {
        this.mockMvc = mockMvc;
    }
}
Bu istek oluşturucu sınıfı işe yaramaz çünkü test edilen sisteme HTTP istekleri oluşturan ve gönderen yöntemleri yazmadık. Spring MVC REST API için birim testleri yazmayı öğrendiğimizde istek oluşturucu sınıfları hakkında daha fazla konuşacağız.

Ek Okuma:

Ardından, test edilen sistemi yapılandırmayı öğreneceğiz.

Test Edilen Sistemi Yapılandırma

Aşağıdaki adımları takip ederek yeni bir test sınıfı oluşturabilir ve test edilen sistemi yapılandırabiliriz:

Öncelikle, yeni bir test sınıfı oluşturup gerekli alanları test sınıfımıza eklemeliyiz. Test sınıfımız iki private alanlar:

  1. bu requestBuilder alan şunları içerir: TodoItemRequestBuilder test edilen sisteme HTTP istekleri gönderirken test yöntemlerimiz tarafından kullanılan nesne.
  2. bu service alan içerir TodoItemCrudService alay Kurulum yöntemlerimiz, Mockito ile yöntemleri saplarken bu alanı kullanacaktır. Ayrıca, test yöntemlerimiz, test edilen sistem ile sahtemiz arasında gerçekleşen veya gerçekleşmeyen etkileşimleri doğrularken bu alanı kullanacaktır.

Test sınıfımızı oluşturduktan sonra kaynak kodu şu şekilde görünür:


class TodoItemCrudControllerTest {

    private TodoItemRequestBuilder requestBuilder;
    private TodoItemCrudService service;
}

İkincibir test yöntemi çalıştırılmadan önce çalıştırılan yeni bir kurulum yöntemi yazdık ve aşağıdaki adımları izleyerek bu yöntemi uyguladık:

  1. Yeni bir tane oluştur TodoItemCrudService oluşturulan alayı alay edin ve saklayın service alan.
  2. Yeni bir tane oluştur TodoItemCrudController nesne (bu test edilen denetleyicidir) ve oluşturulan nesneyi yerel bir değişkende saklayın.
  3. Yeni bir tane oluştur MockMvc bağımsız yapılandırmayı kullanarak nesneyi oluşturun ve oluşturulan nesneyi yerel bir değişkende saklayın. Özel bir hata işleyici sınıfı yapılandırmayı unutmayın (aka @ControllerAdvice sınıf) ve özel HttpMessageConverter Jackson’ı kullanarak JSON okuyabilir ve yazabilir (aka MappingJackson2HttpMessageConverter).
  4. Yeni bir tane oluştur TodoItemRequestBuilder nesne ve oluşturulan nesneyi requestBuilder alan.

Kurulum metodumuzu 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.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);
    }
}
Test edilen sistem özel istisnalar atarsa ​​ve bu istisnaların düzgün bir şekilde ele alındığından emin olmak istiyorsak, kullanılan @ControllerAdvice sınıf (aka hata işleyici sınıfı).

Ek Okuma:

Artık bağımsız yapılandırmayı kullanarak test edilen sistemi yapılandırabiliriz. Bu blog gönderisinden öğrendiklerimizi özetleyelim.

Özet

Bu blog yazısı bize şunu öğretti:

  • Bir kullanarak yinelenen kod yazmadan gerekli özel bileşenleri oluşturabiliriz. public sahip olan nesne ana sınıfı public ve static fabrika yöntemleri.
  • Bir request oluşturucu sınıfı kullanarak yinelenen kod yazmadan test edilen sisteme HTTP istekleri gönderebiliriz.
  • Test edilen sistemi bağımsız yapılandırmayı kullanarak yapılandırmak istiyorsak, standaloneSetup() yöntemi MockMvcBuilders sınıf.
  • yöntemlerini kullanarak test edilen sisteme özel bileşenleri dahil edebiliriz. StandaloneMockMvcBuilder sınıf.
  • Test edilen sisteme dahil edilen en yaygın özel bileşenler şunlardır: @ControllerAdvice sınıf ve ve bir özel HttpMessageConverter Jackson’ı kullanarak JSON okuyabilir ve yazabilir (aka MappingJackson2HttpMessageConverter).

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ı"]