spring boot2.x与junit5集成测试

junit5与junit4区别比较大,junit5使用了大量的jdk8特性,lambda表达式,使用junit5前需要自行脑补jdk8特性

JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

spring boot2.x使用junit5需要使用注解 @ExtendWith(SpringExtension.class),下面的例子使用junit5的参数化测试的功能,即配置测试参数数据源,这里我没有使用junit5的 csv数据源,我采用了自定义扩展数据源方式,使用json数据源的方式。


package com.xxx.junit5.test;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;

import com.alibaba.fastjson.JSONObject;
import com.xxx.spring.SpringBootStarter;
import com.xxx.user.model.UserVO;

/**
 * junit5测试用例
 * 
 * @author xuchang
 */
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = { SpringBootStarter.class })
@AutoConfigureMockMvc
@ExtendWith(SpringExtension.class)
public class TestBizAccount4Junit5 {
    
    /**  */
    @Autowired
    private MockMvc mockMvc;
    
    @Override
    protected MockMvc getMockMvc() {
        return mockMvc;
    }
    
    /**
     * 费用报销单保存测试
     * 
     * 请求URI: "/bizaccount/save"
     * 
     * @param testData xx
     * 
     * @throws Exception 异常
     */
    @ParameterizedTest
    @JsonFileSource(resources = "/com/xxx/junit5/test/testData.json")
    void testSave(JSONObject testData) throws Exception {
        UserVO param = new UserVO();
        param.setName(testData.getString("name"));
        param.setNumber(testData.getString("number"));
        
        ResultActions resultActions = this.getMockMvc()
            .perform(get("/user/testConsumes/{ss}", "xxx").contentType(MediaType.APPLICATION_JSON_UTF8)
                .content(JSONObject.toJSONString(testData)).accept(MediaType.ALL))
            .andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
            .andDo(print());
        resultActions.andReturn();
    }
    
}

 自定义扩展JSON数据源


package com.xxx.junit5.test;

import static org.apiguardian.api.API.Status.EXPERIMENTAL;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.apiguardian.api.API;
import org.junit.jupiter.params.provider.ArgumentsSource;

/**
 * junit5 JSON文件测试数据源
 * 
 * @author xuchang
 */
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = EXPERIMENTAL, since = "5.0")
@ArgumentsSource(JsonFileArgumentsProvider.class)
public @interface JsonFileSource {
    
    /**
     * JSON资源文件路基
     * 
     */
    String[] resources();
    
    /**
     * json文件解析编码格式
     *
     * <p>
     * Defaults to {@code "UTF-8"}.
     *
     * @see java.nio.charset.StandardCharsets
     */
    String encoding() default "UTF-8";
    
}

package com.xxx.junit5.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.function.BiFunction;
import java.util.stream.Stream;

import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.support.AnnotationConsumer;
import org.junit.platform.commons.util.PreconditionViolationException;
import org.junit.platform.commons.util.Preconditions;

import com.alibaba.fastjson.JSONObject;

/**
 * JSON文件参数提供者
 * 
 * @author xuchang
 */
public class JsonFileArgumentsProvider implements ArgumentsProvider, AnnotationConsumer<JsonFileSource> {
    
    private final BiFunction<Class<?>, String, InputStream> inputStreamProvider;
    
    private JsonFileSource annotation;
    
    private String[] resources;
    
    private Charset charset;
    
    JsonFileArgumentsProvider() {
        this(Class::getResourceAsStream);
    }
    
    JsonFileArgumentsProvider(BiFunction<Class<?>, String, InputStream> inputStreamProvider) {
        this.inputStreamProvider = inputStreamProvider;
    }
    
    @Override
    public void accept(JsonFileSource annotation1) {
        this.annotation = annotation1;
        resources = annotation1.resources();
        try {
            this.charset = Charset.forName(annotation1.encoding());
        } catch (Exception ex) {
            throw new PreconditionViolationException("The charset supplied in " + this.annotation + " is invalid", ex);
        }
    }
    
    @Override
    public Stream<? extends Arguments> provideArguments(ExtensionContext context) throws Exception {
        return Arrays.stream(resources).map(resource -> openInputStream(context, resource)).flatMap(this::toStream);
    }
    
    private Stream<Arguments> toStream(InputStream inputStream) {
        JSONObject obj = JSONObject.parseObject(readJSON(inputStream), JSONObject.class);
        return Stream.of(Arguments.of(obj));
    }
    
    /**
     * 读取文件到字符串
     * 
     * @param file 文件
     * @return 文件内容
     */
    private String readJSON(InputStream inputStream) {
        StringBuilder objFile = new StringBuilder(1000);
        // 读取系统换行符
        BufferedReader objReader = null;
        try {
            objReader = new BufferedReader(new InputStreamReader(inputStream, charset));
            String strLine = objReader.readLine();
            while (strLine != null) {
                objFile.append(strLine).append(System.getProperty("line.separator"));
                strLine = objReader.readLine();
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
        return objFile.toString();
    }
    
    private InputStream openInputStream(ExtensionContext context, String resource) {
        Preconditions.notBlank(resource, "Classpath resource [" + resource + "] must not be null or blank");
        Class<?> testClass = context.getRequiredTestClass();
        return Preconditions.notNull(inputStreamProvider.apply(testClass, resource),
            () -> "Classpath resource [" + resource + "] does not exist");
    }
    
    public JsonFileSource getAnnotation() {
        return annotation;
    }
    
    public void setAnnotation(JsonFileSource annotation) {
        this.annotation = annotation;
    }
    
    public String[] getResources() {
        return resources;
    }
    
    public void setResources(String[] resources) {
        this.resources = resources;
    }
    
    public Charset getCharset() {
        return charset;
    }
    
    public void setCharset(Charset charset) {
        this.charset = charset;
    }
    
    public BiFunction<Class<?>, String, InputStream> getInputStreamProvider() {
        return inputStreamProvider;
    }
    
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值