繁体   English   中英

使用NSubstitute模拟IFlurl库方法会引发空引用异常

[英]Mocking IFlurl library methods using NSubstitute is throwing null reference exception

我正在使用flurl,并且尝试对以下代码进行单元测试:

public class MyRestClient
{
    public async Task<T> Request<T>(IFlurlRequest flurlRequest)
    {
        try  
        {
            return await flurlRequest
                    .WithOAuthBearerToken("my-hardcoded-token")
                    .GetAsync()
                    .ReceiveJson<T>();  
        }
        catch(HttpFlurlException)
        {
            throw new MyCustomException();
        }
    }
}

我要测试的是,如果flurlRequest抛出HttpFlurlException类型的异常,则它将抛出MyCustomException 我的想法是发送flurlrequest并引发异常。 这是我布置测试的方式:

var moq = Substitute.For<IFlurlRequest>();
// Problem is with line below:
moq.When(x => x.WithOAuthBearerToken("dummy")).Do(x => { throw new HttpFlurlException(); } );

var myClient = new MyRestClient();

Func<Task> call = async () => { await myClient.Request<object>(moq); };

// FluentAssertions
call.Should().Throw<MyCustomException>();

运行时的代码返回NullReferenceException:

Exception has occurred: CLR/System.NullReferenceException
An exception of type 'System.NullReferenceException' occurred in 
Flurl.Http.dll but was not handled in user code: 'Object reference not 
set to an instance of an object.'
at Flurl.Http.HeaderExtensions.WithHeader[T](T clientOrRequest, String name, Object value)

所以我看到了与标头有关的东西...所以我尝试通过添加以下方法来模拟它:

var moq = Substitute.For<IFlurlRequest>();
moq.Headers.Returns(new Dictionary<string, object> { {"dummy", new {} };

但我不断遇到同样的例外。 我究竟做错了什么?

WithOAuthBearerToken是一个扩展方法,这意味着NSubstitute无法直接对其进行模拟。 当您在扩展方法上调用When..DoReturns时,它将运行该扩展方法的实际代码。 (我建议将NSubstitute.Analyzers添加到测试项目中以检测这些情况。)

在编写本文时跟踪扩展方法的实现,应该可以模拟Headers属性以引发所需的异常,但是我认为这会拖累过多的库内部知识,并且会导致脆弱的测试。与该特定实现紧密结合(这是我们旨在通过模拟避免的目标!)。

正如我在此答案中概述的那样,我将非常谨慎地以这种方式模拟第三方库:

另一个选择是在不同级别进行测试。 我认为测试当前代码的摩擦在于,我们试图替代[第三方库]的详细信息,而不是为分区应用程序的逻辑详细信息而创建的接口。 搜索“不,你没有自己的模拟类型”为什么这可能是一个问题的详细信息(我已经写它之前在这里 )。

如果可能,我建议尝试使用Flurl的内置测试支持 这应该使您能够伪造所需的行为,而无需有关Flurl内部实现的特定详细信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM