gpt4 book ai didi

c# - Nunit 测试 MVC 站点

转载 作者:太空狗 更新时间:2023-10-29 21:35:58 29 4
gpt4 key购买 nike

我在尝试对我拥有的 MVC 站点进行单元测试时遇到了一些问题:我需要运行大量的 ASP.NET 环境(生成 httpcontexts、 session 、cookie、成员资格等)全面测试一切。

即使是测试一些不太前端的东西也需要成员(member)资格才能正常工作,而且手动欺骗这一切是很挑剔的。

有没有办法在 NUnit 测试中启动应用程序池?这似乎是最简单的方法。

最佳答案

如果编写得当,您不需要真实的上下文、真实的 session 、cookie 等。默认情况下,MVC 框架提供了一个可以模拟/ stub 的 HttpContext。我建议使用像 Moq 或 Rhino Mocks 这样的模拟框架,并创建一个 MockHttpContext 类,该类创建一个模拟上下文,其中包含您需要针对设置进行测试的所有属性。这是一个使用 Moq 的模拟 HttpContext

/// <summary>
/// Mocks an entire HttpContext for use in unit tests
/// </summary>
public class MockHttpContextBase
{
/// <summary>
/// Initializes a new instance of the <see cref="MockHttpContextBase"/> class.
/// </summary>
public MockHttpContextBase() : this(new Mock<Controller>().Object, "~/")
{
}

/// <summary>
/// Initializes a new instance of the <see cref="MockHttpContextBase"/> class.
/// </summary>
/// <param name="controller">The controller.</param>
public MockHttpContextBase(Controller controller) : this(controller, "~/")
{
}

/// <summary>
/// Initializes a new instance of the <see cref="MockHttpContextBase"/> class.
/// </summary>
/// <param name="url">The URL.</param>
public MockHttpContextBase(string url) : this(new Mock<Controller>().Object, url)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="MockHttpContextBase"/> class.
/// </summary>
/// <param name="controller">The controller.</param>
/// <param name="url">The URL.</param>
public MockHttpContextBase(ControllerBase controller, string url)
{
HttpContext = new Mock<HttpContextBase>();
Request = new Mock<HttpRequestBase>();
Response = new Mock<HttpResponseBase>();
Output = new StringBuilder();

HttpContext.Setup(x => x.Request).Returns(Request.Object);
HttpContext.Setup(x => x.Response).Returns(Response.Object);
HttpContext.Setup(x => x.Session).Returns(new FakeSessionState());

Request.Setup(x => x.Cookies).Returns(new HttpCookieCollection());
Request.Setup(x => x.QueryString).Returns(new NameValueCollection());
Request.Setup(x => x.Form).Returns(new NameValueCollection());
Request.Setup(x => x.ApplicationPath).Returns("~/");
Request.Setup(x => x.AppRelativeCurrentExecutionFilePath).Returns(url);
Request.Setup(x => x.PathInfo).Returns(string.Empty);

Response.Setup(x => x.Cookies).Returns(new HttpCookieCollection());
Response.Setup(x => x.ApplyAppPathModifier(It.IsAny<string>())).Returns((string path) => path);
Response.Setup(x => x.Write(It.IsAny<string>())).Callback<string>(s => Output.Append(s));

var requestContext = new RequestContext(HttpContext.Object, new RouteData());
controller.ControllerContext = new ControllerContext(requestContext, controller);
}

/// <summary>
/// Gets the HTTP context.
/// </summary>
/// <value>The HTTP context.</value>
public Mock<HttpContextBase> HttpContext { get; private set; }

/// <summary>
/// Gets the request.
/// </summary>
/// <value>The request.</value>
public Mock<HttpRequestBase> Request { get; private set; }

/// <summary>
/// Gets the response.
/// </summary>
/// <value>The response.</value>
public Mock<HttpResponseBase> Response { get; private set; }

/// <summary>
/// Gets the output.
/// </summary>
/// <value>The output.</value>
public StringBuilder Output { get; private set; }
}

/// <summary>
/// Provides Fake Session for use in unit tests
/// </summary>
public class FakeSessionState : HttpSessionStateBase
{
/// <summary>
/// backing field for the items in session
/// </summary>
private readonly Dictionary<string, object> _items = new Dictionary<string, object>();

/// <summary>
/// Gets or sets the <see cref="System.Object"/> with the specified name.
/// </summary>
/// <param name="name">the key</param>
/// <returns>the value in session</returns>
public override object this[string name]
{
get
{
return _items.ContainsKey(name) ? _items[name] : null;
}
set
{
_items[name] = value;
}
}
}

您可以进一步添加一些东西,例如 HTTP header 集合,但希望它能演示您可以做什么。

使用

var controllerToTest = new HomeController();
var context = new MockHttpContextBase(controllerToTest);

// do stuff that you want to test e.g. something goes into session

Assert.IsTrue(context.HttpContext.Session.Count > 0);

关于成员(member)资格提供商或其他提供商,您遇到了一些难以测试的问题。我会抽象接口(interface)背后提供者的用法,这样您就可以在测试依赖它的组件时为接口(interface)提供伪造。但是,您仍然无法对使用提供程序的接口(interface)的具体实现进行单元测试,但是关于单元测试和代码覆盖率您想要/必须走多远,您的里程可能会有所不同。

关于c# - Nunit 测试 MVC 站点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7476041/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com