尝试使用 UrlHelper 测试控制器
Trying to Test a Controller with a UrlHelper
尝试创建 URLHelper
用于测试目的会引发 NullReferenceException
。
示例:
[Fact]
public async void AuthenticateAsyncTest()
{
// Arrange
var controller = new Controller(serviceProvider)
{
Url = new UrlHelper(new ActionContext()) // Exception thrown
};
// Act
var result = await controller.Authenticate() as ViewResult;
// Assert
Assert.NotNull(result);
}
每次我运行这个测试,在Url = new UrlHelper(new ActionContext())
中抛出的异常是:
Exception.Message:
Message: System.NullReferenceException : Object reference not set to
an instance of an object.
Exception.StackTrace:
UrlHelperBase.ctor(ActionContext actionContext)
ControllerUnitTest.AuthenticateAsyncTest()
使用:
xUnit 2.4.1,
Microsoft.NETCore.App 2.2.0,
Microsoft.AspNetCore.Routing.Abstractions 2.2.0
重新创建异常:
- 创建一个空的 MVC 核心 2.2 解决方案
- 创建一个 xunit 测试项目
- 安装 NuGet Microsoft.AspNetCore.Mvc.Core 2.2.0
- 在测试中写入:var Url = new UrlHelper(new ActionContext());
- 运行 测试
应该是这样的:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Routing;
using Xunit;
namespace XUnitTestProject1
{
public class UnitTest1
{
[Fact]
public void Test1()
{
var Url = new UrlHelper(new ActionContext());
}
}
}
我的问题:
- 是否有错误,或者为什么这不起作用?
- 解决方法的文献或链接是否受到赞赏?
根据异常消息引用的GitHub source code,
protected UrlHelperBase(ActionContext actionContext)
{
if (actionContext == null)
{
throw new ArgumentNullException(nameof(actionContext));
}
ActionContext = actionContext;
AmbientValues = actionContext.RouteData.Values;
_routeValueDictionary = new RouteValueDictionary();
}
助手正在尝试访问原始示例中未提供的 actionContext.RouteData.Values
。
为测试提供必要的依赖关系以完成。
[Fact]
public async Task AuthenticateAsyncTest() {
// Arrange
var httpContext = new DefaultHttpContext();
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
var controller = new Controller(serviceProvider) {
Url = new UrlHelper(actionContext)
};
// Act
var result = await controller.Authenticate() as ViewResult;
// Assert
Assert.NotNull(result);
}
同时避免在单元测试中使用 async void。请改用 Task
。
第二种选择是使用特定的构造函数。该文档声明它应该用于单元测试,更具体地说,当 ActionContext 只需要传入,但不被消费代码使用时。
UrlHelper Url = new UrlHelper(new ActionContext { RouteData = new RouteData() });
感谢 navelDirt 和 pranavkm 在 githhub 上的回放:
https://github.com/aspnet/AspNetCore/issues/6703
尝试创建 URLHelper
用于测试目的会引发 NullReferenceException
。
示例:
[Fact]
public async void AuthenticateAsyncTest()
{
// Arrange
var controller = new Controller(serviceProvider)
{
Url = new UrlHelper(new ActionContext()) // Exception thrown
};
// Act
var result = await controller.Authenticate() as ViewResult;
// Assert
Assert.NotNull(result);
}
每次我运行这个测试,在Url = new UrlHelper(new ActionContext())
中抛出的异常是:
Exception.Message:
Message: System.NullReferenceException : Object reference not set to an instance of an object.
Exception.StackTrace:
UrlHelperBase.ctor(ActionContext actionContext) ControllerUnitTest.AuthenticateAsyncTest()
使用:
xUnit 2.4.1, Microsoft.NETCore.App 2.2.0, Microsoft.AspNetCore.Routing.Abstractions 2.2.0
重新创建异常:
- 创建一个空的 MVC 核心 2.2 解决方案
- 创建一个 xunit 测试项目
- 安装 NuGet Microsoft.AspNetCore.Mvc.Core 2.2.0
- 在测试中写入:var Url = new UrlHelper(new ActionContext());
- 运行 测试
应该是这样的:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Routing;
using Xunit;
namespace XUnitTestProject1
{
public class UnitTest1
{
[Fact]
public void Test1()
{
var Url = new UrlHelper(new ActionContext());
}
}
}
我的问题:
- 是否有错误,或者为什么这不起作用?
- 解决方法的文献或链接是否受到赞赏?
根据异常消息引用的GitHub source code,
protected UrlHelperBase(ActionContext actionContext)
{
if (actionContext == null)
{
throw new ArgumentNullException(nameof(actionContext));
}
ActionContext = actionContext;
AmbientValues = actionContext.RouteData.Values;
_routeValueDictionary = new RouteValueDictionary();
}
助手正在尝试访问原始示例中未提供的 actionContext.RouteData.Values
。
为测试提供必要的依赖关系以完成。
[Fact]
public async Task AuthenticateAsyncTest() {
// Arrange
var httpContext = new DefaultHttpContext();
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
var controller = new Controller(serviceProvider) {
Url = new UrlHelper(actionContext)
};
// Act
var result = await controller.Authenticate() as ViewResult;
// Assert
Assert.NotNull(result);
}
同时避免在单元测试中使用 async void。请改用 Task
。
第二种选择是使用特定的构造函数。该文档声明它应该用于单元测试,更具体地说,当 ActionContext 只需要传入,但不被消费代码使用时。
UrlHelper Url = new UrlHelper(new ActionContext { RouteData = new RouteData() });
感谢 navelDirt 和 pranavkm 在 githhub 上的回放: https://github.com/aspnet/AspNetCore/issues/6703