如何断言 API 响应具有特定结构?

How to assert that a API response has a specific structure?

我设置了一个 SpecFlow 测试定义,我想断言该响应在其响应中具有特定的字段集合。例如,我有来自 API:

的特殊预期响应
{
    isActive: false,
    lastProcessed: "2020-11-03T19:03:16.537"

}

我要验证的是响应包含这两个字段,不一定是这些字段包含的值。我尝试了以下方法:

Assert.NotNull(response.Model.isActive);
Assert.NotNull(response.Model.lastProcessed);

但我在使用此方法时遇到错误: Do not use Assert.NotNull() on value type 'bool'

除了使用“NotNull()”之外,我还能如何确保响应结构符合预期?

解决方案: 按照接受的答案,我将从 API 调用返回的模型序列化为 JSON 并将其解析为 JObject。然后我使用 ContainsKey() 方法断言它。

JObject jObject = JObject.Parse(JsonConvert.SerializeObject(response.Model));
Assert.True(jObject.ContainsKey("isActive"));

我不知道你使用什么包来发送请求和反序列化,但如果你可以将响应内容作为原始 json 字符串获取,那么你可以使用 Newtonsoft.JSON 将响应解析为JObjectJObject.Parse(responseContent)JObject有个方法叫ContainsKey(propertyName),判断对象中是否有指定名称的字段。您可以断言如果它 returns 对于所需的 属性 名称为真。

编辑

关于下面 Greg 的回答。原始错误实际上是由 bool 不是可空类型引起的,在模型中使其可为空可以修复错误。然而,这个解决方案并不理想。在某些情况下,null 可能是 API 返回的有效值,这会产生漏报。例如如果我们收到:

{
    isActive: null,
    lastProcessed: "2020-11-03T19:03:16.537"
}

那么 Assert.NotNull(response.Model.isActive) 会产生一个否定的测试结果,即使该字段存在于 json 中,这就是我们想要检查的内容。

所以理论上,如果我们 100% 确定 null 永远不会被 API 本身返回,那么我们可以那样做,但它不会是一个通用的方法。也没有很好地描述我们正在努力实现的目标 ;)

因为 isActive 属性 是一个 bool 你需要断言它是假的。相反,如果您想要一个 true 或 false 值,然后用一些东西来表示它丢失了,请在您的 DTO 中使用可为 null 的布尔值:

public class YourDTO
{
    public bool? isActive { get; set; }
    ...
}

然后您可以断言 isActive 为 null、true 或 false。


备选方案: 如果您无法更新原始数据传输对象,那么这可能是编写您自己的代码来调用 Web 服务并映射 JSON 对您自己的仅用于测试的 DTO 的响应。

但是,这可能是一项大量的工作。优点是您的测试代码与它测试的代码真正分离。我也对使用数据库的应用程序完成了此操作。这是额外的工作,但它允许您的测试使用对测试有意义的任何数据结构。