匿名 JSON 对象集合的单元测试

2023-12-03

这个问题的灵感来自于此很好的例子。我有 ASP.NET Core MVC 应用程序,我正在编写单元测试对于控制器。其中一种方法返回JsonResult具有匿名类型的集合。我可以找到集合中的每个元素。我还可以像这样断言每个元素中的值:

Dictionary<int, string> expectedValues = new Dictionary<int, string> {
    { 1, "Welcome Tester"},
    { 2, "Namaste Tester"},
    { 3, "Privet Tester"},
    { 4, "Labdien Tester"}
};
foreach (dynamic value in jsonCollection) {
    dynamic json = new DynamicObjectResultValue(value);
    Assert.Equal(expectedValues[json.Id], json.Greeting);
}

但是有没有办法对整个集合做出断言呢?例如,Assert.Equal(4, jsonCollection.Count()) or Assert.Contains(2, jsonCollection[Id])(这显然是伪代码)。


这是动态对象包装器的更新版本。

public static class DynamicObjectWrapperExtension {
    /// <summary>
    /// Return provided object as a <seealso cref="System.Dynamic.DynamicObject"/>
    /// </summary>  
    public static dynamic AsDynamicObject(this object value) {
        return new DynamicObjectWrapper(value);
    }
}

public class DynamicObjectWrapper : DynamicObject, IEquatable<DynamicObjectWrapper> {
    private readonly object value;
    private readonly Type valueType;

    public DynamicObjectWrapper(object value) {
        this.value = value;
        this.valueType = value.GetType();
    }

    public override IEnumerable<string> GetDynamicMemberNames() {
        return valueType.GetProperties().Select(p => p.Name);
    }

    public override bool TryConvert(ConvertBinder binder, out object result) {
        result = null;
        try {
            result = changeTypeCore(value, binder.Type);
        } catch {
            return false;
        }
        return true;
    }

    private object changeTypeCore(object value, Type convertionType) {
        if (ReferenceEquals(value, null))
            return getDefaultValueForType(convertionType);

        var providedType = valueType;
        if (convertionType.IsAssignableFrom(providedType)) {
            return value;
        }

        try {
            var converter = TypeDescriptor.GetConverter(convertionType);
            if (converter.CanConvertFrom(providedType)) {
                return converter.ConvertFrom(value);
            }

            converter = TypeDescriptor.GetConverter(providedType);
            if (converter.CanConvertTo(providedType)) {
                return converter.ConvertTo(value, convertionType);
            }
        } catch {
            return value;
        }

        try {
            return Convert.ChangeType(value, convertionType, System.Globalization.CultureInfo.CurrentCulture);
        } catch {
            return value;
        }
    }

    private object getDefaultValueForType(Type targetType) {
        return targetType.IsClass || targetType.IsInterface ? null : Activator.CreateInstance(targetType);
    }

    public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) {
        result = null;
        //1d collection
        if (potentialIndex(indexes)) {
            int index = (int)indexes[0];
            var list = value as IList;
            if (validIndex(index, list)) {
                result = checkValue(list[index]);
                return true;
            }
        }
        return false;
    }

    private bool validIndex(int index, IList list) {
        return index >= 0 && index < list.Count;
    }

    private bool potentialIndex(object[] indexes) {
        return indexes[0] != null && typeof(int) == indexes[0].GetType() && value is IList;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result) {
        return TryGetValue(binder.Name, out result);
    }

    public bool TryGetValue(string propertyName, out object result) {
        result = null;
        var property = valueType.GetProperty(propertyName);
        if (property != null) {
            var propertyValue = property.GetValue(value, null);
            result = checkValue(propertyValue);
            return true;
        }
        return false;
    }

    private object checkValue(object value) {
        var valueType = value.GetType();
        return isAnonymousType(valueType)
            ? new DynamicObjectWrapper(value)
            : value;
    }

    private bool isAnonymousType(Type type) {
        //HACK: temporary hack till a proper function can be implemented
        return type.Namespace == null &&
            type.IsGenericType &&
            type.IsClass &&
            type.IsSealed &&
            type.IsPublic == false;
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) {
        try {
            result = valueType.InvokeMember(
                binder.Name,
                BindingFlags.InvokeMethod |
                BindingFlags.Public |
                BindingFlags.Instance,
                null, value, args);

            return true;
        } catch {
            result = null;
            return false;
        }
    }

    public override bool Equals(object obj) {
        // If parameter is null return false.
        if (ReferenceEquals(obj, null)) return false;

        // Return true if the fields match:
        return this.value == obj || (obj is DynamicObjectWrapper && Equals(obj as DynamicObjectWrapper));
    }

    public bool Equals(DynamicObjectWrapper other) {
        // If parameter is null return false.
        if (ReferenceEquals(other, null)) return false;
        // Return true if the fields match:
        return this.value == other.value;
    }

    public override int GetHashCode() {
        return ToString().GetHashCode();
    }

    public override string ToString() {
        var name = GetType().Name;
        return string.Format("{0}[{1}]", name, value);
    }

}

假设以下控制器

public class FooController : Controller {

    public IActionResult GetAnonymousObject() {

        var jsonResult = new {
            id = 1,
            name = "Foo",
            type = "Bar"
        };

        return Json(jsonResult);
    }

    public IActionResult GetAnonymousCollection() {

        var jsonResult = Enumerable.Range(1, 20).Select(x => new {
            id = x,
            name = "Foo" + x,
            type = "Bar" + x
        }).ToList();

        return Json(jsonResult);
    }
}

使用示例

[TestClass]
public class DynamicObjectWrapperTests {
    [TestMethod]
    public void DynamicObjectResultValue_Member_Should_Exist() {
        //Arrange
        var controller = new FooController();

        //Act
        var result = controller.GetAnonymousObject() as JsonResult;

        //Assert
        dynamic obj = result.Value.AsDynamicObject();

        Assert.IsNotNull(obj);
        Assert.AreEqual(1, obj.id);
        Assert.AreEqual("Foo", obj.name);
        Assert.AreEqual(3, obj.name.Length);
        Assert.AreEqual("Bar", obj.type);
    }

    [TestMethod]
    public void DynamicObjectResultValue_DynamicCollection() {
        //Arrange
        var controller = new FooController();

        //Act
        var result = controller.GetAnonymousCollection() as JsonResult;

        //Assert
        dynamic jsonCollection = result.Value;
        foreach (object value in jsonCollection) {
            dynamic json = value.AsDynamicObject();

            Assert.IsNotNull(json.id,
                "JSON record does not contain \"id\" required property.");
            Assert.IsNotNull(json.name,
                "JSON record does not contain \"name\" required property.");
            Assert.IsNotNull(json.type,
                "JSON record does not contain \"type\" required property.");
        }
    }

    [TestMethod]
    public void DynamicObjectResultValue_DynamicCollection_Should_Convert_To_IEnumerable() {
        //Arrange
        var controller = new FooController();

        //Act
        var result = controller.GetAnonymousCollection() as JsonResult;
        dynamic jsonCollection = result.Value.AsDynamicObject();
        int count = 0;
        foreach (var value in jsonCollection) {
            count++;
        }

        //Assert
        Assert.IsTrue(count > 0);
    }

    [TestMethod]
    public void DynamicObjectResultValue_DynamicCollection_Index_at_0_Should_Not_be_Null() {
        //Arrange
        var controller = new FooController();

        //Act
        var result = controller.GetAnonymousCollection() as JsonResult;
        dynamic jsonCollection = result.Value.AsDynamicObject();

        //Assert                
        Assert.IsNotNull(jsonCollection[0]);
    }

    [TestMethod]
    public void DynamicObjectResultValue_DynamicCollection_Should_Be_Indexable() {
        //Arrange
        var controller = new FooController();

        //Act
        var result = controller.GetAnonymousCollection() as JsonResult;
        dynamic jsonCollection = result.Value.AsDynamicObject();

        //Assert
        for (var i = 0; i < jsonCollection.Count; i++) {

            var json = jsonCollection[i];

            Assert.IsNotNull(json);
            Assert.IsNotNull(json.id,
               "JSON record does not contain \"id\" required property.");
            Assert.IsNotNull(json.name,
                "JSON record does not contain \"name\" required property.");
            Assert.IsNotNull(json.type,
                "JSON record does not contain \"type\" required property.");

        }
    }

    [TestMethod]
    public void DynamicObjectResultValue_DynamicCollection_Count_Should_Be_20() {
        //Arrange
        var controller = new FooController();

        //Act
        var result = controller.GetAnonymousCollection() as JsonResult;

        //Assert
        dynamic jsonCollection = result.Value.AsDynamicObject();

        Assert.AreEqual(20, jsonCollection.Count);
    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

匿名 JSON 对象集合的单元测试 的相关文章

  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 如何从 Visual Studio 将视图导航到其控制器?

    问题是解决方案资源管理器上有 29 个项目 而且项目同时具有 ASP NET MVC 和 ASP NET Web 表单结构 在MVC部分中 Controller文件夹中有大约100个子文件夹 每个文件夹至少有3 4个控制器 视图完全位于不同
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • 在 Unity 中实现 Fur with Shells 技术

    我正在尝试在 Unity 中实现皮毛贝壳技术 http developer download nvidia com SDK 10 5 direct3d Source Fur doc FurShellsAndFins pdf Fins 技术被
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • WcfSvcHost 的跨域异常

    对于另一个跨域问题 我深表歉意 我一整天都在与这个问题作斗争 现在已经到了沸腾的地步 我有一个 Silverlight 应用程序项目 SLApp1 一个用于托管 Silverlight SLApp1 Web 的 Web 项目和 WCF 项目
  • C# - 当代表执行异步任务时,我仍然需要 System.Threading 吗?

    由于我可以使用委托执行异步操作 我怀疑在我的应用程序中使用 System Threading 的机会很小 是否存在我无法避免 System Threading 的基本情况 只是我正处于学习阶段 例子 class Program public
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • 如何定义一个可结构化绑定的对象的概念?

    我想定义一个concept可以检测类型是否T can be 结构化绑定 or not template
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • C# 动态/expando 对象的深度/嵌套/递归合并

    我需要在 C 中 合并 2 个动态对象 我在 stackexchange 上找到的所有内容仅涵盖非递归合并 但我正在寻找能够进行递归或深度合并的东西 非常类似于jQuery 的 extend obj1 obj2 http api jquer
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 对于某些 PDF 文件,LoadIFilter() 返回 -2147467259

    我正在尝试使用 Adob e IFilter 搜索 PDF 文件 我的代码是用 C 编写的 我使用 p invoke 来获取 IFilter 的实例 DllImport query dll SetLastError true CharSet
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使
  • 使用 WGL 创建现代 OpenGL 上下文?

    我正在尝试使用 Windows 函数创建 OpenGL 上下文 现代版本 基本上代码就是 创建窗口类 注册班级 创建一个窗口 choose PIXELFORMATDESCRIPTOR并设置它 创建旧版 OpenGL 上下文 使上下文成为当前

随机推荐

  • 如何从 python 更改 Linux 用户密码

    我在从 python 更改 Linux 用户密码时遇到问题 我已经尝试了很多方法 但无法解决问题 这是我已经尝试过的示例 sudo password是sudo的密码 sudo command是我希望系统运行的命令 user 是从列表中获取的
  • 什么是跳表?

    有人可以解释一下跳转表的机制以及为什么嵌入式系统需要它吗 跳转表可以是函数指针数组 也可以是机器代码跳转指令数组 如果您有一组相对静态的函数 例如系统调用或类的虚拟函数 那么您可以创建此表一次并使用数组的简单索引来调用函数 这意味着检索指针
  • R 中的分桶数据

    我正在尝试创建一个函数 根据给定的向量确定某个值进入哪个存储桶 所以我的函数有两个输入 一个确定存储桶断点的向量 例如 如果向量是 1 4 5 10 则桶将 我现在的做法是首先检查输入数字是否大于向量的最大元素或小于向量的最小元素 如果没有
  • 如何在拖动开始之前缓存整个图层并在拖动结束时将其恢复回来?

    我目前正在尝试稍微加快我的移动设备网络应用程序的速度 但现在我陷入了最重要的部分 缓存 如何在用户开始拖动之前缓存整个图层 并在拖动操作停止时将其恢复为可用的 Kinetic Nodes 现在我开始缓存 stage on mousedown
  • 图像分割结果中的噪声

    我正在做一个基于深度卷积神经网络的图像分割任务 网络结构来自这张纸 其结构如图所示 FCN在图像分割中的应用 该网络的设计基于全卷积网络 and DCAN 该数据集为腺体分割挑战赛公开基准数据集2015年米卡展会 也称为 Warwick Q
  • 为什么结构体中的双精度成员未在 8 字节边界上对齐?

    这是关于内存对齐的 在下面的代码中 我预计结构内 b 的偏移量为 8 32 位机器 看here 从而 使b总是发生在缓存行内 然而 事实并非如此 会员b在全局对象中struct test1似乎是对齐的 我不确定这是偶然的还是编译器故意这样做
  • 从 byte[] 返回文件下载

    这段代码 string xml XmlHelper ToXml queryTemplate byte xmlb StringHelper GetBytes xml var cd new System Net Mime ContentDisp
  • 如何在不使用 JSF 中隐藏标签的情况下将 javascript 内的值传递给托管 bean 属性?

    我们想知道是否可以在 Facelets 中的 javascript 方法内获取托管 bean 属性值 或者将 javascript 值传递给托管 bean 属性但不使用隐藏标记 当我们搜索它们时 我们看到的都是关于使用html隐藏标签或隐藏
  • 实体框架多对多查询:未生成导航属性

    我有两张桌子User and UserRole它们是使用链接表连接的UserInRole 当我生成实体模型时 由于某种原因 实体UserInRole没有生成 从图中可以看出 实体框架理解之间存在多对多关系User and UserRole
  • 如何细分/细化 xarray 数据集中的维度?

    Summary 我有一个数据集 其收集方式使得维度最初不可用 我想获取本质上是一大块无差别的数据 并为其添加维度 以便可以对其进行查询 子集化等 这是以下问题的核心 这是我拥有的 xarray 数据集
  • 如何将 Activator.CreateInstance 返回的对象转换为它转换的类型?

    在下面的代码中 是否可以将 x 转换为您要传递的类型Activator CreateInstance提前不知道是什么 我尝试传入typeof 但这行不通 var testClasses AppDomain CurrentDomain Get
  • 使用java识别文件扩展名

    我在数据库中有不同格式的文件 我想复制到我的本地机器 我如何识别文件格式 doc xls 等 问候 克里希纳 谢谢 您提供建议 根据您的建议 我编写了代码并且已经完成 请查看我的博客 我在这里发布了代码 http muralie39 wor
  • 在 Win32 上,如何使用 Perl、Python 或 Ruby(或 C)检测是否按下了 Left Shift 或 Right ALT?

    在 Win32 上 我想知道如何使用 Perl Python 或 Ruby 甚至在 C 中 检测是否按下了 Left Shift 或 Right ALT 不仅仅是当前窗口 而是整个全局环境 示例 当我输入文档时 我可以按右 ALT 启动用
  • 在没有 root 访问权限的服务器上安装 Docker 二进制文件

    我有一个由提供商提供的服务器 没有任何根访问权限 无法在 etc 或 var lib docker 中编写脚本 Docker 未安装 我的想法是在目录中安装并运行 docker 二进制文件 我将使用 shell 脚本安装 docker 该脚
  • Excel vba xml解析性能

    我正在努力在 Excel 中获取一些输入数据 将其解析为 xml 并使用它来运行 SQL 存储过程 但我遇到了 xml 解析的性能问题 输入表看起来像这样 Dates Name1 Name2 Name3 NameX Date1 Date2
  • 获取子文件夹Azure数据工厂中的所有文件名

    我在数据湖中有一个以下文件夹结构 我想从 ParentFolder 目录的所有子文件夹中获取所有 csv 文件名 我的所有文件都是 csv 文件 是否有一种使用元数据活动的简单方法 父文件夹 gt 年 2020 文件夹 2020 10 20
  • 防止滑动 UIPageViewController 时出现白色间隙

    我以这种方式实现了 UIPageViewController GalleryViewController 是PageViewController的容器 PageViewController 是 uipageViewController 我将
  • 如何使用C#计算段落中某个单词的数量

    我正在尝试编写一个程序 用户向系统提供一个单词和一个段落 系统的工作是计算该单词出现的次数 如何计算 C 中该单词出现的次数 使用正则表达式字边界 anchor int wordCount Regex Matches text b Rege
  • Inno Setup 桌面快捷方式(链接),其中设置了“以管理员身份运行”高级属性

    我正在努力让 Inno setup 5 5 9u 创建一个带有图标并具有高级属性的桌面快捷方式 以管理员身份运行 set Issue 这个问题与以下问题有点不同 如何使用 Inno Setup 在文件上设置 以管理员身份运行 因为我想做的不
  • 匿名 JSON 对象集合的单元测试

    这个问题的灵感来自于此很好的例子 我有 ASP NET Core MVC 应用程序 我正在编写单元测试对于控制器 其中一种方法返回JsonResult具有匿名类型的集合 我可以找到集合中的每个元素 我还可以像这样断言每个元素中的值 Dict