我正在ASP.NET Core中构建一个Web API,我想对控制器进行单元测试.
我注入了一个数据访问接口,我可以很容易地模拟.但是控制器必须检查Request for a token中的头部,并且当我自己简单地实例化控制器时,该请求似乎不存在,并且它也是get-only,所以我甚至无法手动设置它.我发现了许多模拟ApiController的例子,但这不是.NET核心.还有很多关于如何对.net核心控制器进行单元测试的教程和示例,但实际上没有使用过HttpRequest.
我建立了一个MCVE来证明这一点:
[Produces("application/json")]
[Route("api/Players")]
public class PlayersController : Controller
{
private IAccessor accessor;
public PlayersController(IAccessor ac = null):base()
{
accessor = ac ?? AccessorFactory.GetAccessor();
}
/// <summary>
/// Get all players. Must be logged in.
/// </summary>
/// <returns>Ok or Unauthorized.</returns>
[HttpGet]
public IActionResult Get()
{
Player client = accessor.GetLoggedInPlayer(Request.Headers["token"]); // NRE here because Request is null
if (client == null) return Unauthorized();
return Ok(accessor.GetAllPlayers());
}
}
Run Code Online (Sandbox Code Playgroud)
我在我的测试项目中使用Moq和MSTest,并注入一个模拟的IAccessor.如何注入请求,或使用控制器初始化它?我想我的最后一招是反思,但我真的想避免这种情况.
我正在尝试为这种方法编写一些单元测试,但我无法弄清楚如何设置Request.具体来说,我需要设置Query和头属性Referer.
public IActionResult Index()
{
if (User.Identity.IsAuthenticated)
{
return RedirectToAction("Index", "Home");
}
var query = Request.Query;
StringValues returnUrlValue;
if (query.TryGetValue("returnUrl", out returnUrlValue))
{
var returnUrl = returnUrlValue.ToString();
var referer = Request.Headers["Referer"].ToString();
if (string.IsNullOrEmpty(returnUrl) && !string.IsNullOrEmpty(referer))
{
returnUrl = WebUtility.UrlEncode(referer);
}
if (Url.IsLocalUrl(returnUrl) && !string.IsNullOrEmpty(returnUrl))
{
ViewBag.ReturnUrl = returnUrl;
}
}
return View();
}
Run Code Online (Sandbox Code Playgroud)
我知道在request进入控制器之前经过中间件,所以它不能作为参数传递给控制器.但是,Request控制器上的对象是readonly,也不能分配.因此,类似下面的内容将无法正常工作.
var controller = new LoginController();
controller.Request = new DefaultHttpRequest(new DefaultHttpContext())
{
QueryString = new …Run Code Online (Sandbox Code Playgroud) 使用:NETCore.App 1.1,xunit 2.2.0-beta4-build3444,Moq 4.6.38-alpha.
我试图测试一个ASP.Net核心控制器,它需要一个名为"X-ClientID"的标头出现在请求中.我现在写了我的测试函数如下:
[Fact]
public void Test1()
{
var controller = new GraphController(this.positiveAuthorizer, this.loggerFactory, this.elasticsearchSettings);
controller.Request.Headers.Add("X-ClientID", "1234");
var result = controller.Get("calls", "year", "day", "1", "sliding", new DateTime(2016, 11, 1)).Result;
// TODO: Write assert statements on result
}
Run Code Online (Sandbox Code Playgroud)
positiveAuthorizer,loggerFactory并且elasticsearchSettings是使用Moq的模拟类,它们在控制器内按预期工作.
不过controller.Request是null.此外,controller.Request是get-only,所以我无法将其设置为新值.
如何在调用控制器之前设置X-Client标头?
我想对我的控制器进行单元测试,但我在读取值时遇到问题HttpContext.Session。
我想从我的控制器中模拟这一部分:HttpContext.Session.Get<int>(Foo)
使用Mock HttpContext 对 .NET core MVC 控制器进行单元测试?以及 如何在 asp net core 中模拟会话对象我能够得出以下解决方案:
我的测试:
public void GetFoos_AllGood_ReturnList()
{
//Arrange
Mock<ISession> sessionMock = new Mock<ISession>();
var fooSessionValue = new byte[0];
Web.Controllers.FooController fooController = new Web.Controllers.FooController();
fooController.ControllerContext.HttpContext = new DefaultHttpContext();
fooController.ControllerContext.HttpContext.Request.Headers["Foo"] = 0;
Mock<IServiceCollection> mock = new Mock<IServiceCollection>();
mock.Object.AddSession(); // Tried this, but failed
//Setup
sessionMock.Setup(_ => _.Set("Foo", It.IsAny<byte[]>())).Callback<string, byte[]>((k, v) => fooSessionValue = v);
sessionMock.Setup(_ => _.TryGetValue("Foo", out fooSessionValue)).Returns(true);
mockWebDataManager.Setup(b => b.GetFoos(It.IsAny<FooArgs>())).Returns(new FooResult() { …Run Code Online (Sandbox Code Playgroud) 假设我有一个最基本的控制器
public class HomeController : Controller
{
public ActionResult Index(string id, string language)
{
return View();
}
}
Run Code Online (Sandbox Code Playgroud)
其中包含2个参数.但是,有一个要求是调用action方法的客户端应该id从URL 传递值,但是language从http头传递值.这意味着url应该是/Home/Index/12345,同时调用客户端将设置Http Header值language : en.
如何在MVC5或MVC6中设置路由以达到要求?
请不要提供Web Api的样本.
谢谢
c# asp.net asp.net-mvc-routing asp.net-mvc-5 asp.net-core-mvc
因此,我创建了一个 .net 核心中间件,用于向响应添加标头。我没有找到对这个中间件进行单元测试的方法,因为它使用OnStarting回调,我无法想象如何模拟或强制执行它。
这是中间件的示例:
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
context.Response.OnStarting(() =>
{
context.Response.Headers.Add("Name", "Value");
return Task.CompletedTask;
});
await next(context);
}
Run Code Online (Sandbox Code Playgroud)
由于中间件接口需要 的具体实例HttpContext,例如,我无法想象使用 来模拟它的方法FakeItEasy。
我有一个 asp .net 核心项目,实际上在我们使用 session 的每个操作中,我的问题是如果我没有 sessionRepository 如何测试它。控制器测试崩溃,因为控制器中的会话为空。我尝试 Moq IHttpContextAcessor 并且它也不起作用。
我试试这个:
HttpContext.Current = new HttpContext(new HttpRequest(null, "http://tempuri.org", null), new HttpResponse(null));
Run Code Online (Sandbox Code Playgroud)
但 HttpContext 不包含 Current 的定义。(使用 Microsoft.AspNetCore.Http;)
有没有办法对使用 HttpContext 和会话的最小起订量或测试控制器进行测试?
c# ×7
asp.net-core ×5
xunit ×4
unit-testing ×3
asp.net ×2
moq ×2
.net ×1
middleware ×1
mocking ×1
testing ×1
xunit.net ×1