воскресенье, 11 июня 2017 г.

Spring boot. Тестирование web приложения

Рассмотрим процесс тестировани веб приложения. Для начала создадим тестовое веб приложение, очень похожее на пример из 1 части, только без БД.
Сущность:
package com.entity;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class JournalEntry {
    private String title;
    private Date created;
    private String summary;
    private final SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
    public JournalEntry(String title, String summary, String date) throws
            ParseException{
        this.title = title;
        this.summary = summary;
        this.created = format.parse(date);
    }
    JournalEntry(){}
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public Date getCreated() {
        return created;
    }
    public void setCreated(String date) throws ParseException {
        Long _date = null;
        try{
            _date = Long.parseLong(date);
            this.created = new Date(_date);
            return;
        }catch(Exception ignored){}
        this.created = format.parse(date);
    }
    public String getSummary() {
        return summary;
    }

    public void setSummary(String summary) {
        this.summary = summary;
    }
    public String toString(){
        return "* JournalEntry(" + "Title: " +
                title +
                ",Summary: " +
                summary +
                ",Created: " +
                format.format(created) +
                ")";
    }
}
Контроллер:
package com.controller;

import com.entity.JournalEntry;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@RestController
public class JournalController {
    private static List<JournalEntry> entries = new ArrayList<JournalEntry>();
    static {
        try {
            entries.add(new JournalEntry("Get to know Spring Boot", "Today I will learn Spring Boot", "01/01/2016"));
            entries.add(new JournalEntry("Simple Spring Boot Project", "I will do my first Spring Boot Project", "01/02/2016"));
            entries.add(new JournalEntry("Spring Boot Reading", "Read more about Spring Boot", "02/01/2016"));
            entries.add(new JournalEntry("Spring Boot in the Cloud", "Spring Boot using Cloud Foundry", "03/01/2016"));
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    @RequestMapping("/journal/all")
    public List<JournalEntry> getAll() throws ParseException{
        return entries;
    }

    @RequestMapping("/journal/findBy/title/{title}")
    public List<JournalEntry> findByTitleContains(@PathVariable String title) throws
            ParseException{
        return entries
                .stream()
                .filter(entry -> entry.getTitle().toLowerCase().contains(title.toLowerCase()))
                .collect(Collectors.toList());
    }

    @RequestMapping(value="/journal",method = RequestMethod.POST )
    public JournalEntry add(@RequestBody JournalEntry entry){
        entries.add(entry);
        return entry;
    }
}
Рассмотрим класс для тестирования:
package com;

import com.entity.JournalEntry;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.mock.http.MockHttpOutputMessage;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;

import javax.annotation.Resource;

import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.iterableWithSize;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
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;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Arrays;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@WebAppConfiguration
public class SpringBootApplicationTest {
    private final String SPRING_BOOT_MATCH = "Spring Boot";
    private final String CLOUD_MATCH = "Cloud";
    private HttpMessageConverter mappingJackson2HttpMessageConverter;
    private MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(),
            MediaType.APPLICATION_JSON.getSubtype(),
            Charset.forName("utf8"));
    private MockMvc mockMvc;

    @Autowired
    private WebApplicationContext webApplicationContext;
    @Autowired
    void setConverters(HttpMessageConverter<?>[] converters) {
        this.mappingJackson2HttpMessageConverter = Arrays.stream(converters).
                filter(
                        converter -> converter instanceof MappingJackson2HttpMessageConverter).
                findAny().get();
    }

    @Before
    public void setup() throws Exception {
        this.mockMvc = webAppContextSetup(webApplicationContext).build();
    }

    @Test
    public void getAll() throws Exception {
        mockMvc.perform(post("/journal")
                .content(this.toJsonString(new JournalEntry("Spring Boot Testing","Create Spring Boot Tests","05/09/2016")))
                .contentType(contentType)).andExpect(status().isOk());
        mockMvc.perform(get("/journal/all"))
                .andExpect(status().isOk())
                .andExpect(content().contentType(contentType))
                .andExpect(jsonPath("$",iterableWithSize(5)))
                .andExpect(jsonPath("$[0]['title']",containsString(SPRING_BOOT_MATCH)));
    }

    @Test
    public void findByTitle() throws Exception {
        mockMvc.perform(get("/journal/findBy/title/" + CLOUD_MATCH))
                .andExpect(status().isOk())
                .andExpect(content().contentType(contentType))
                .andExpect(jsonPath("$",iterableWithSize(1)))
                .andExpect(jsonPath("$[0]['title']",containsString(CLOUD_MATCH)));
    }

    @Test
    public void add() throws Exception {
        mockMvc.perform(post("/journal")
                .content(this.toJsonString(new JournalEntry("Spring Boot Testing","Create Spring Boot Tests","05/09/2016")))
                        .contentType(contentType)).andExpect(status().isOk());
    }

    @SuppressWarnings("unchecked")
    protected String toJsonString(Object obj) throws IOException {
        MockHttpOutputMessage mockHttpOutputMessage = new MockHttpOutputMessage();
        this.mappingJackson2HttpMessageConverter.write(obj, MediaType.APPLICATION_JSON,
                mockHttpOutputMessage);
        return mockHttpOutputMessage.getBodyAsString();
    }
}
После этого можно запускать тесты отдельно или все вместе, запустив сам класс SpringBootApplicationTest. Если запускать весь класс - нет возможности влиять на порядок запускаемых тестов, для этого придумана аннотация FixMethodOrde, передав туда MethodSorters.DEFAULT - методты будут запускать по порядку расположения в классе, MethodSorters.NAME_ASCENDING - по имени

Комментариев нет :

Отправить комментарий