为什么在使用 MSpec/Moq 测试此异步方法时会收到 NullReferenceException?

2023-12-26

我想测试异步方法是否返回正确的类型。此方法使用依赖类中的另一个异步方法。依赖类实现此接口:

Task<string> DownloadStringAsync(string url);

我想测试的方法是这样的:

public async Task<T> GetData<T>(string url) where T : class , new()
{
    var jsonData = await _webClientWrapper.DownloadStringAsync(url);

    if (string.IsNullOrEmpty(jsonData))
        return new T();

    try
    {
        return await JsonConvert.DeserializeObjectAsync<T>(jsonData);
    }
    catch (JsonException inner)
    {
        throw new JsonConvertException("Error converting Json string", inner) { JsonString = jsonData };
    }
}

使用 xUnit 和 Moq 进行测试成功:

public class Testes
{
    private const string ValidJson = "{'Nome':'Rogerio','Idade':'51'}";
    protected static JsonWebServiceClassProvider JsonWebServiceClassProvider;
    private static Mock<IWebClientWrapper> _webClientWrapperMoq;
    private static FakeClassFromJson _resultClass;

    [Fact]
    public async static void When_calling_GetData_it_should_return_a_class_of_same_type()
    {
        _webClientWrapperMoq = new Mock<IWebClientWrapper>();
        _webClientWrapperMoq
            .Setup(w => w.DownloadStringAsync(Moq.It.IsAny<string>()))
            .Returns(Task.FromResult(ValidJson));

        JsonWebServiceClassProvider = new JsonWebServiceClassProvider(_webClientWrapperMoq.Object);

        _resultClass = await JsonWebServiceClassProvider
            .GetData<FakeClassFromJson>(Moq.It.IsAny<string>());

        Assert.IsType<FakeClassFromJson>(_resultClass);
    }
}

使用 MSpec 和 Moq 进行测试:

[Subject("JsonWebServiceClassProvider")]
public class When_calling_GetData_with_a_valid_Json_Service_Url
{
    private const string ValidJson = "{'Nome':'Rogerio','Idade':'51'}";
    protected static JsonWebServiceClassProvider JsonWebServiceClassProvider;
    protected static Mock<IWebClientWrapper> WebClientWrapperMoq;
    protected static FakeClassFromJson ResultClass;

    Establish context = () =>
    {
        WebClientWrapperMoq = new Mock<IWebClientWrapper>();
        WebClientWrapperMoq
            .Setup(w => w.DownloadStringAsync(Moq.It.IsAny<string>()))
            .Returns(Task.FromResult(ValidJson));

        JsonWebServiceClassProvider = new JsonWebServiceClassProvider(WebClientWrapperMoq.Object);
    };

    Because of = () => ResultClass = JsonWebServiceClassProvider
        .GetData<FakeClassFromJson>(Moq.It.IsAny<string>())
        .Await();

    It should_return_a_class_of_same_type = () => ResultClass.ShouldBeOfType<FakeClassFromJson>();
}

这些也失败了Because声明

Because of = () => JsonWebServiceClassProvider
    .GetData<FakeClassFromJson>(Moq.It.IsAny<string>())
    .ContinueWith(task => ResultClass = task.Result)
    .Wait();

Because of = () => ResultClass = JsonWebServiceClassProvider
    .GetData<FakeClassFromJson>(Moq.It.IsAny<string>())
    .Result;

这失败了NullReferenceException在行中

public async Task<T> GetData<T>(string url) where T : class , new()
{
    string jsonData = await _webClientWrapper.DownloadStringAsync(url);
    // ...
}

SOLVED

在等待响应的同时,进行了一些重构,瞧!我创建了一个基类Establish语句并在那里启动模拟对象:

public class JsonWebServiceClassProviderSpecs
{
    protected static JsonWebServiceClassProvider JsonWebServiceClassProvider;
    protected static Mock<IWebClientWrapper> WebClientWrapperMoq; 

    Establish context = () =>
    {
        WebClientWrapperMoq = new Mock<IWebClientWrapper>();
        JsonWebServiceClassProvider = new JsonWebServiceClassProvider(WebClientWrapperMoq.Object);
    };
}

我更新了测试类:

[Subject("JsonWebServiceClassProvider")]
public class When_ask_data_with_a_valid_Json_Service_Url : JsonWebServiceClassProviderSpecs
{
    private const string ValidJson = "{'Nome':'Rogerio','Idade':'51'}";
    protected static FakeClassFromJson ResultClass;

    Establish context = () =>
    {
        WebClientWrapperMoq
            .Setup(w => w.DownloadStringAsync(Moq.It.IsAny<string>()))
            .Returns(Task.FromResult(ValidJson));
    };

    Because of = () => ResultClass = JsonWebServiceClassProvider
        .GetData<FakeClassFromJson>(Moq.It.IsAny<string>())
        .Await();

    It should_return_a_class_of_same_type = () => ResultClass.ShouldBeOfType<FakeClassFromJson>();
}

这是您的规范的精简版本,可以使用。不NullReferenceException被看到。 笔记:

  • The It不检查的类型AwaitResult而是被包裹起来Task.Result
  • 我没有通过Moq.It<string>.Any... in the Because,噪音太大了。如果忽略该参数,请使用传达该事实的值。

(只是一些文本,以便下面的代码块格式正确。)

using System.Diagnostics;
using System.Threading.Tasks;

using Machine.Specifications;

using Moq;

using YourApp;

using It = Machine.Specifications.It;

namespace YourApp
{
  class Foo
  {
  }

  public interface IWebClientWrapper
  {
    Task<string> DownloadStringAsync(string url);
  }

  public class JsonWebServiceClassProvider
  {
    readonly IWebClientWrapper _webClientWrapper;

    public JsonWebServiceClassProvider(IWebClientWrapper webClientWrapper)
    {
      _webClientWrapper = webClientWrapper;
    }

    public async Task<T> GetData<T>(string url) where T : class, new()
    {
      string jsonData = await _webClientWrapper.DownloadStringAsync(url);
      Debug.Assert(jsonData != null);
      return new T();
    }
  }
}

namespace Specs
{
  public class When_calling_GetData_with_a_valid_Json_Service_Url
  {
    const string ValidJson = "{'Nome':'Rogerio','Idade':'51'}";
    static JsonWebServiceClassProvider JsonWebServiceClassProvider;
    static Mock<IWebClientWrapper> Wrapper;
    static AwaitResult<Foo> Result;

    Establish context = () =>
    {
      Wrapper = new Mock<IWebClientWrapper>();
      Wrapper.Setup(w => w.DownloadStringAsync(Moq.It.IsAny<string>()))
             .Returns(Task.FromResult(ValidJson));

      JsonWebServiceClassProvider = new JsonWebServiceClassProvider(Wrapper.Object);
    };

    Because of = () => Result = JsonWebServiceClassProvider.GetData<Foo>("ignored").Await();

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

为什么在使用 MSpec/Moq 测试此异步方法时会收到 NullReferenceException? 的相关文章

  • 请求的资源不支持 HTTP 方法“GET”

    我的路线配置正确 并且我的方法具有装饰标签 我仍然收到 请求的资源不支持 HTTP 方法 GET 消息 System Web Mvc AcceptVerbs GET POST System Web Mvc HttpGet public st
  • 根据另一个列表的内容对列表进行排序

    我有一个包含整数列表的列表和另一个包含同时包含整数和字符串的类的列表 我想做的是按字母顺序对列表进行排序 将第一个列表中存在的条目放在前面 这是我的代码和预期输出 using System using System Collections
  • 使用inotify监控文件

    我正在使用 inotify 来监视本地文件 例如使用 root temp inotify add watch fd root temp mask 删除该文件后 程序将被阻止read fd buf bufSize 功能 即使我创建一个新的 r
  • 获取光标相对于控件的位置 - C#

    我想获取鼠标相对于鼠标指针所在控件的位置 这意味着当我将光标置于控件的起点 左上角 时 它应该给出 0 0 我正在使用以下代码 private void panel1 MouseMove object sender MouseEventAr
  • 堆栈独立的C/C++蓝牙API?

    我想知道是否有适用于 Windows XP Vista 7 x86 和 x64 的堆栈独立 C C 蓝牙 api 我的目标是创建连接并通过蓝牙发送 接收一些时间关键的数据 我的研究给了我以下选择以及这项任务的缺点 用于蓝牙的 Windows
  • 为什么 CMake 不通过在定义该变量之前创建的 CMAKE_CXX_STANDARD 将语言标准编译标志添加到目标?

    我在用着cmake version 3 22 1 and c Ubuntu 11 3 0 1ubuntu1 22 04 11 3 0 以及非常简约的CMakeLists txt 我无法让 CMAKE 使用 C 20 Setting set
  • 将 gcov 与 CMake/CDash 结合使用的详细指南?

    我在我的项目中使用 CMake 并设置了 cdash 服务器以进行连续 夜间构建 一切运行良好 通过设置 crontab 我们可以将每小时 每晚的构建 测试结果自动上传到我们的 cdash 服务器 我的下一步是将测试覆盖率报告添加到构建中
  • DLL 需要访问其应用程序的符号

    在 C 中 DLL 是否可以访问加载它的应用程序的某些符号 我有一个加载插件 dll 的应用程序 这些插件需要访问该应用程序的某些API 是否可以在不创建共享此 API 的新 DLL 的情况下实现此目的 函数指针结构适合这种情况吗 示例 主
  • 如何使用 ASP.NET MVC 4.0 DonutOutputCache VaryByCustom 使缓存失效

    我正在为我的 ASP NET 应用程序使用 DevTrends MvcDonutCaching 包 它工作得很好 我目前遇到的一个问题是使我为子操作设置的 VaryByCustom 缓存无效 这是我用于 VaryByCustom 设置的一些
  • 为什么long long 2147483647 + 1 = -2147483648? [复制]

    这个问题在这里已经有答案了 为什么这段代码不打印相同的数字 long long a b a 2147483647 1 b 2147483648 printf lld n a printf lld n b 我知道int变量的最大数量是2147
  • 如何检查是否发生溢出? [复制]

    这个问题在这里已经有答案了 可能的重复 检测 C C 中整数溢出的最佳方法 https stackoverflow com questions 199333 best way to detect integer overflow in c
  • 那里有更好的 DateTime.Parse 吗? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有谁知道有一个库 付费或免费 能够处理比 DateTime Parse 使用的更常见的日期时间格式 能够
  • 如何定义 Swagger UI 参数的默认值?

    我已将 Swagger Swashbuckle 集成到 NET Core 2 2 API 项目中 一切都很好 我的要求纯粹是为了方便 考虑以下 API 方法 public Model SomeEstimate SomeRequest req
  • “sizeof”对不完整类型列表结构 C 的无效应用

    我正在尝试实现一种处理页面错误的替换算法 因此 我尝试使用 malloc 创建一个循环链表 但出现以下错误 无效的应用程序sizeof to incomplete typepageInMemory 以下是代码 typedef struct
  • Cuda:最小二乘求解,速度较差

    最近 我使用Cuda编写了一个名为 正交匹配追踪 的算法 在我丑陋的 Cuda 代码中 整个迭代需要 60 秒 而 Eigen lib 只需 3 秒 在我的代码中 矩阵 A 是 640 1024 y 是 640 1 在每一步中 我从 A 中
  • 正则表达式基于组的不同替换?

    所以我对正则表达式比较陌生 并且做了一些练习 我正在玩一个简单的 混淆器 它只是寻找 dot or dot or at or at 不区分大小写 并且在匹配项之前或之后有或没有任意数量的空格 这是针对通常情况的 someemail AT d
  • Python 中的 C 指针算术

    我正在尝试将一个简单的 C 程序转换为 Python 但由于我对 C 和 Python 都一无所知 这对我来说很困难 我被 C 指针困住了 有一个函数采用 unsigned long int 指针并将其值添加到 while 循环中的某些变量
  • 任何浮点密集型代码是否会在任何基于 x86 的架构中产生位精确的结果?

    我想知道使用浮点运算的 C 或 C 代码是否会在任何基于 x86 的体系结构中产生位精确的结果 无论代码的复杂性如何 据我所知 自 Intel 8087 以来的任何 x86 架构都使用准备处理 IEEE 754 浮点数的 FPU 单元 并且
  • 构建 OpenCV 时出错 :: MonitorFromRect 未在此范围内声明

    我试图建立OpenCV version 2 4 8与它一起使用CodeBlocks and MinGw 我按照以下指示进行操作here http kevinhughes ca tutorials opencv install on wind
  • AddressAccessDeniedException :无需 netsh 即可解决它?

    我遇到了异常AddressAccessDeniedException因为我的processus没有注册URL的权限 我首先以管理员身份运行我的程序 好的 它成功了 但我现在想要分发我的应用程序 并且我希望每个用户都能够运行它 而不必成为管理

随机推荐

  • 在文本字符串中查找特定术语并在上一列中返回该术语

    由于某种原因 我无法弄清楚第一个返回是否有效 但是当我向下拖动时 其他结果返回为 VALUE IF FIND Drummondville B3 gt 0 Drummondville IF FIND Saint Germain de gran
  • 检查设备是否可以使用 Cordova 解码视频

    我在用着VR view https developers google com vr concepts vrview在我的 Ionic Cordova 应用程序中 VR view 的文档指出 某些较旧的设备无法解码大于 1080p 1920
  • 设置 RStudio Portable 默认 R 版本

    我最近发现了 R 和 RStudio 的便携式版本 http rportable sourceforge net http rportable sourceforge net 开源岩石 无论如何 我在大学里从一台电脑跳到另一台电脑 我想让
  • 如何以 Rails 形式链接下拉菜单

    如何在 Rails 页面上链接下拉菜单 两个下拉列表都来自数据库 例如 如果第一个下拉列表是category 即将形成category桌子 第二次下降 products 也来自数据库 将根据第一个下拉菜单的选择进行填充 您可以使用 coll
  • SQL Server 中有类似“生存时间”的选项吗?

    SQL Server 中有类似 生存时间 的选项吗 最近我了解了Scylla DB中的Time to Live 我想知道跨数据库尤其是 SQL Server 是否可以使用相同的选项 我在 Internet 上搜索过 但找不到 SQL Ser
  • SQL对多个表建立索引,可以做到吗?

    一直在寻找解决方案一段时间了 转到 1 或 2 跳过描述 首先我会解释一下情况 我公司已经升级了我们的 erp 系统 我的主要工作是创建公司其他人使用的列表 我从该系统数据库中获取所有数据 在升级过程中 我们转换了一些数据以匹配新版本 其中
  • 什么是 MySQL 外键?

    在 Stack Overflow 的一个回答中 我看到了这段代码 CREATE TABLE Favorites user id INT NOT NULL movie id INT NOT NULL PRIMARY KEY user id m
  • Sql - SELECT 行,直到行的总和达到某个值

    我在这里看到了其他类似的问题 但它们并不能完全满足我的需求 至少我是这么认为的 我有一个包含以下列的 receipts 表 收据 客户ID 数量 让我们说 我有 5 张来自客户 1 的未付款收据 reciept id 1 Ammount 1
  • 如何链接到 boost date_time

    Example 我有一个 Rcpp 函数 我想调用它boost posix time time from string 我从以下位置获取了示例代码增强文档 https www boost org doc libs 1 65 0 doc ht
  • Java包循环检测:如何找到涉及的具体类? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 您推荐什么工具来检测Java包循环依赖 知道目标是明确列出检测到的 跨包循环 中涉及的特定类 我知道关于
  • ASP.NET 中的基本表单身份验证有多安全?

    想象一下 您有一个只有 2 个页面的简单网站 login aspx 和 Secret aspx 仅使用 ASP net 表单身份验证和 login aspx 上的 ASP net 登录服务器控件来保护您的站点 详情如下所示 该站点配置为使用
  • 如何在mySQL中动态选择列名

    我想选择列名 但我事先不知道表结构 并且它可能会改变 所以我不能只用列名对 select 语句进行硬编码 我也不想选择每一列 有没有简单的方法可以做到这一点 我的想法是这两个查询的某种组合 但我的 SQL 不是那么好 SHOW COLUMN
  • 是什么导致我的参数超出范围异常? [复制]

    这个问题在这里已经有答案了 我试图测试我的列表是否正在从数据库收集数据 但是当我尝试获取消息框以从列表中打印邮政编码时 它给了我例外 System ArgumentOutOfRangeException 索引超出范围 必须为非负数且小于集合
  • Android 图像缓存 - 如何?

    我想以前已经问过很多次了 但仍然有些事情我不太明白 我尝试了两种不同的方法 将所有图像保留在内存中 当开始超过一定限制时 开始删除它们 让 Android 使用 SoftReferences 解决这个问题 2 有时 我分配它们时 它只是清理
  • 如何处理文件路径中的 ~

    我正在编写一个简单的命令行 Java 实用程序 我希望用户能够使用以下命令传递相对于其主目录的文件路径 操作员 所以像 Documents 我的问题是有没有办法让Java自动解析这种类型的路径 或者我是否需要扫描文件路径 操作员 看来这种类
  • 为什么 Perl 函数“map”给出错误“Map 参数不足”

    这是我不明白的事情 该脚本工作正常 注意映射函数中的串联 usr bin perl use strict use warnings use Data Dumper my aa map a gt 1 1 3 print Dumper aa E
  • 使用 Jinja2 在 html 文件中嵌入 png 图像

    我正在使用 Jinja2 将 html 报告创建为单个 html 文件 我想在 html 文件中包含公司徽标 而不是链接到它 这样 即使阅读报告的人处于离线状态 也会显示徽标 使用 Jinja2 可以自动完成此操作吗 如果不是 我如何手动在
  • 我可以阻止手机在网页上休眠吗

    在应用程序中我可以使用http developer android com reference android os PowerManager WakeLock html http developer android com referen
  • 虚函数表偏移量

    我想问一下 类的虚函数表的偏移量取决于什么 我的意思是 从我读到的内容来看 它至少取决于编译器 但它是否因类而异 编辑 通过偏移我的意思是表相对于所有者对象的地址的位置 编辑 示例代码 void vtable void char objec
  • 为什么在使用 MSpec/Moq 测试此异步方法时会收到 NullReferenceException?

    我想测试异步方法是否返回正确的类型 此方法使用依赖类中的另一个异步方法 依赖类实现此接口 Task