.net core集成测试之Post请求

Web项目中,很多与用户数据交互的请求都是Post请求,想必大家都用过HttpClient构造过post请求,这里并不对HttpClient做详细介绍,只介绍一些常用的功能.并结合AutoFixture演示如何自动构造请求数据,简单手动创建Json或者Formdata的工作量,提高生产效率.

我们为上节创建的HelloWorld控制器添加一个StudentInfo方法,内容如下

       [HttpPost]
        public IActionResult StudentInfo(Student student)
        {
            return Content(student.Name);
        }

这个方法的参数是一个Student类型的对象,和早期版本mvc并没有太大差别,我们把这个Student类的代码贴出来:

 public class Student
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public byte Gender { get; set; }
        public string School { get; set; }
    }

下面我们来构造一个对StudentInfo的请求测试方法.

       [Fact]
        public async Task SimplePost()
        {
            Dictionary<string, string> dict = new Dictionary<string, string>
            {
                {"name","sto"},
                {"age","32" },
                {"gender","2" },
                {"school","middleschool" }
            };
            var response = await _client.PostAsync("/HelloWorld/StudentInfo", new FormUrlEncodedContent(dict));
            response.EnsureSuccessStatusCode();
            var result =await response.Content.ReadAsStringAsync();
            Assert.Equal("sto", result);
        }

以上代码可能大家都非常熟悉了.我们用dictionary对象构造了formdata然后做为post请求内容发送到服务端,服务端返回的是接收到的student对象的name属性,这里我们验证服务端返回的name是不是我们传过去的"sto".

然而这样做是非常耗时的,如果只写一两个测试方法还好,对成千上百个方法这样构建参数是非常繁琐和乏味的,并且如果后端对数据有限制的情况下想构造出来符合条件的数据更是麻烦,并且后端接口如果字段有修改则有可能造成测试失败.由于测试项目引用了mvc项目,因此我们可以访问到mvc项目里的这些类型,然后使用AutoFixture动态创建这些类型的实例,然后序列化为Json提交,这样会明显减少工作量并增加程序的可维护性.

AutoFixture的安装前面也提到过,并且它是支持.net core的,我们在Nuget包管理工具界面输入AutoFixture.Xunit2进行搜索,然后下载这个包即可,如果直接下载它则不用下载AutoFixture包,因为它是这个包的一个依赖,会自动安装.

改造后的方法如下:

        [Theory]
        [AutoData]
        public async Task SimplePost(Student stud)
        {
            var content = new StringContent(JsonConvert.SerializeObject(stud), Encoding.UTF8, "application/json");
            var response = await _client.PostAsync("/HelloWorld/StudentInfo", content);
            response.EnsureSuccessStatusCode();
            var result =await response.Content.ReadAsStringAsync();
             Assert.True(!string.IsNullOrEmpty(result));
        }

首先fact注解变成了Theory注解,我们知道要为测试方法添加参数需要使用Theory注解,下面添加了AutoData注解,添加以后AutoFixture就会自动为方法的参数提供值.

下面我们把stud对象序列化为json字符串,然后包装成一个stringcontent对象提交到后台,由于传入的是什么值是AutoFixture随机创建的,我们并不知道,因此不能像上面一样断言它是"sto",但是它一定是有值的,因此我们断言它不是null或者空字符串.

然而遗憾的是,以上测试却没有通过,我们看一下错误面板信息:

.netcore持续集成测试篇之Xunit结合netcore内存服务器发送post请求-LMLPHP
通过面板信息我们看到AutoFixture构建的对象Name里是有值的,然而却返回的False,我们只知道结果,其中的过程我们并不清楚,也很难直观的看到错误原因,这时候我们使用调试模式来启动测试程序

首先我们在测试方法刚进入的时候打上断点,看看传入的有没有值
.netcore持续集成测试篇之Xunit结合netcore内存服务器发送post请求-LMLPHP

进入mvc项目,在方法刚进入的地方也打上断点
.netcore持续集成测试篇之Xunit结合netcore内存服务器发送post请求-LMLPHP

下面我们对测试方法执行调试

.netcore持续集成测试篇之Xunit结合netcore内存服务器发送post请求-LMLPHP
我们点击这个红叉就会出现一个浮动面板

.netcore持续集成测试篇之Xunit结合netcore内存服务器发送post请求-LMLPHP
下面有两个按钮一个是运行一个是调试,点击调试就可以进入调试模式了.

第一个断点处我们看到stud的每一个字段都是有值的

.netcore持续集成测试篇之Xunit结合netcore内存服务器发送post请求-LMLPHP

按下F5继续,进入mvc方法里的断点
.netcore持续集成测试篇之Xunit结合netcore内存服务器发送post请求-LMLPHP
我们看到这里每个字段绑定的都是默认值,也就是我们传入的值并没有绑定成功.

以上的调试是为了展示如何调试mvc测试项目,以上单步调试并不能帮助我们太多,其实是因为.net core mvc改变了以往的绑定方式,改成了webapi 2.0的绑定方式,也就是要显式的给参数加上FromBody注解方可成功绑定json数据

我们改一下Mvc里的方法,增加一个frombody注解

        [HttpPost]
        public IActionResult StudentInfo([FromBody]Student student)
        {
            return Content(student.Name);
        }

我们再次运行,就能够正确绑定值了.

08-14 20:14