使用 FromBody 参数 Web 的 MS 测试 API

MS Test with FromBody parameter Web API

我有一个 C# .Net Web API,我正在编写并尝试为一种方法构建 MSTest。

控制器

     public IHttpActionResult BlahMethod([FromBody] dynamic data)
        {
                string id = data.id;
                List<Property> Props = JsonConvert.DeserializeObject<List<Property>>(data.properties.ToString());
                User existing = _context.MyClass.Where(x => x.Properties.Any(y => y.PropertyLabel == "app" && y.PropertyValue == id)).FirstOrDefault();
                    return Json(existing);
        }

我正在尝试使用类似于下面的模拟来测试此方法

测试方法

[TestMethod]
public void AllUsersTest()
{
    var mockSet = new Mock<DbSet<MyClass>>();
    var mockContext = new Mock<DBContext>();
    mockContext.Setup(m => m.MyClass).Returns(mockSet.Object);

    MyController controller = new MyController();
    List<Property> Props = new List<Property>() {
        new Property(){ PropertyLabel = "Nickname", PropertyValue = "TMoney"}
    };
    dynamic data = new TestObject("id", Props);
    var x = controller.BlahMethod(data);
    Assert.IsTrue(true);
}

public class TestObject {
    public TestObject() { }
    public TestObject(string id, List<Property> props)
    {
        this.id = id;
        this.properties = props;
    }
    public string id { get; set; }
    public List<Property> properties { get; set; } = new List<Property>();

}    
public class Property{
     public string PropertyLabel {get; set;}
     public string PropertyValue {get; set;}
  }

我似乎遇到了 JsonReaderException 问题。由于某种原因,错误是说有一个意想不到的角色。我也尝试过发送一个动态对象,这也导致了一个问题。也许有人对使用发布数据在 .net 中模拟 APIs 的最佳方法有一些建议?

该错误是您控制器中以下行的结果:

List<Property> Props = JsonConvert.DeserializeObject<List<Property>>(data.properties.ToString());

在这一行中,您首先将属性转换为字符串,然后尝试反序列化该字符串。但是,转换为字符串与序列化为 JSON 不同。所以对 DeserializeObject 的调用接收到一个无效的字符串并抛出错误。

在 Web API 中,您可以将接收到的数据模型定义为 classes,框架将为您处理反序列化。因此,您可以在项目中简单地定义一个包含所有必需属性的 class。基本上,您可以将 TestObject class 从测试项目移动到 Web API 项目并执行如下操作:

public IHttpActionResult BlahMethod([FromBody] TestObject data)
{
  string id = data.id;
  var Props = data.properties;
  User existing = _context.MyClass.Where(x => x.Properties.Any(y => y.PropertyLabel == "app" && y.PropertyValue == id)).FirstOrDefault();
  if (existing == null)
    return NotFound();
  return Ok(existing);
}

更改后的操作确实通过使用 TestObject 作为参数来定义所需的输入数据。如果您使用 JSON 调用操作,Web API 框架会在调用您的操作之前为您转换它。
在该方法中,您直接处理数据,return 现有用户也作为对象。 Web API 框架采用 return 参数并将其序列化,以便调用者可以理解格式(通常为 JSON)。

至于您的单元测试,您可以像之前那样创建一个示例 TestObject 并根据测试用例的要求设置属性。您直接使用数据调用操作。