测试由 Refit 实现的 API 时出现 NullReferenceException
NullReferenceException when testing API implemented by Refit
我正在尝试使用 Refit 测试一些错误响应(BadRequest、Unauthorized ...),因此我实现了一个 TestHandler returns 任何所需的响应。响应在“OK”(HTTP 状态代码 200)响应下工作正常:
public class Program
{
private static async Task Main()
{
var api = RestService.For<ITest>(
new HttpClient(new TestHandler(HttpStatusCode.OK))
{
BaseAddress = new Uri("https://example.com")
}
);
Console.WriteLine(await api.Test("foo").ConfigureAwait(false));
}
}
public interface ITest
{
[Get("/foo/{bar}")]
Task<string> Test(string bar);
}
public class TestHandler : HttpMessageHandler
{
private readonly HttpResponseMessage _response;
public TestHandler(HttpStatusCode httpStatusCode)
=> _response = new HttpResponseMessage(httpStatusCode) { Content = new StringContent("Yay!") };
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
=> Task.FromResult(_response);
}
但是,每当我将响应状态代码更改为例如 BadRequest (400)、NotFound (404) 或 Unauthorized (401) 时,Refit 都会抛出 NullReferenceException
:
Object reference not set to an instance of an object.
at Refit.DefaultApiExceptionFactory.<CreateExceptionAsync>d__4.MoveNext() in /_/Refit/RefitSettings.cs:line 183
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at Refit.RequestBuilderImplementation.<>c__DisplayClass14_0`2.<<BuildCancellableTaskFuncForMethod>b__0>d.MoveNext() in /_/Refit/RequestBuilderImplementation.cs:line 313
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at RefitTest.Program.<Main>d__0.MoveNext() in C:\Users\Rob\Source\Repos\RefitTest\RefitTest\Program.cs:line 18
这指向RefitSettings.cs line 183。但我不明白为什么 200 OK 会起作用而其他任何反应都不起作用?我做错了什么?
编辑:为了进一步调试,我克隆了 Refit 并将 Refit NuGet 包交换为对 Refit 项目的项目引用。这导致 InvalidOperationException: ITest doesn't look like a Refit interface. Make sure it has at least one method with a Refit HTTP method attribute and Refit is installed in the project
。另外,退回几个版本(我已经转到 5.2.4)也无济于事。
在同事的帮助下找到了!原来 HttpResponseMessage
需要 some/any RequestMessage
.
改变
public TestHandler(HttpStatusCode httpStatusCode)
=> _response = new HttpResponseMessage(httpStatusCode)
{
Content = new StringContent("Yay!")
};
收件人:
public TestHandler(HttpStatusCode httpStatusCode)
=> _response = new HttpResponseMessage(httpStatusCode)
{
RequestMessage = new(), // <-- This one here...
Content = new StringContent("Yay!")
};
它按预期工作。正如在问题(和评论)中,我很接近,但显然是半睡半醒,因为它正是它指向我的地方。
我已提交问题 here。
我正在尝试使用 Refit 测试一些错误响应(BadRequest、Unauthorized ...),因此我实现了一个 TestHandler returns 任何所需的响应。响应在“OK”(HTTP 状态代码 200)响应下工作正常:
public class Program
{
private static async Task Main()
{
var api = RestService.For<ITest>(
new HttpClient(new TestHandler(HttpStatusCode.OK))
{
BaseAddress = new Uri("https://example.com")
}
);
Console.WriteLine(await api.Test("foo").ConfigureAwait(false));
}
}
public interface ITest
{
[Get("/foo/{bar}")]
Task<string> Test(string bar);
}
public class TestHandler : HttpMessageHandler
{
private readonly HttpResponseMessage _response;
public TestHandler(HttpStatusCode httpStatusCode)
=> _response = new HttpResponseMessage(httpStatusCode) { Content = new StringContent("Yay!") };
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
=> Task.FromResult(_response);
}
但是,每当我将响应状态代码更改为例如 BadRequest (400)、NotFound (404) 或 Unauthorized (401) 时,Refit 都会抛出 NullReferenceException
:
Object reference not set to an instance of an object.
at Refit.DefaultApiExceptionFactory.<CreateExceptionAsync>d__4.MoveNext() in /_/Refit/RefitSettings.cs:line 183
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at Refit.RequestBuilderImplementation.<>c__DisplayClass14_0`2.<<BuildCancellableTaskFuncForMethod>b__0>d.MoveNext() in /_/Refit/RequestBuilderImplementation.cs:line 313
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at RefitTest.Program.<Main>d__0.MoveNext() in C:\Users\Rob\Source\Repos\RefitTest\RefitTest\Program.cs:line 18
这指向RefitSettings.cs line 183。但我不明白为什么 200 OK 会起作用而其他任何反应都不起作用?我做错了什么?
编辑:为了进一步调试,我克隆了 Refit 并将 Refit NuGet 包交换为对 Refit 项目的项目引用。这导致 InvalidOperationException: ITest doesn't look like a Refit interface. Make sure it has at least one method with a Refit HTTP method attribute and Refit is installed in the project
。另外,退回几个版本(我已经转到 5.2.4)也无济于事。
在同事的帮助下找到了!原来 HttpResponseMessage
需要 some/any RequestMessage
.
改变
public TestHandler(HttpStatusCode httpStatusCode)
=> _response = new HttpResponseMessage(httpStatusCode)
{
Content = new StringContent("Yay!")
};
收件人:
public TestHandler(HttpStatusCode httpStatusCode)
=> _response = new HttpResponseMessage(httpStatusCode)
{
RequestMessage = new(), // <-- This one here...
Content = new StringContent("Yay!")
};
它按预期工作。正如在问题(和评论)中,我很接近,但显然是半睡半醒,因为它正是它指向我的地方。
我已提交问题 here。