【问题标题】:How to fake ASP.NET MVC UrlHelper with FakeitEasy如何使用 FakeitEasy 伪造 ASP.NET MVC UrlHelper
【发布时间】:2022-10-24 10:08:08
【问题描述】:

这是我的控制器的代码:

private readonly ILMS_Service lms_client;
private UrlHelper urlHelper;

public PackagesController(ILMS_Service client, UrlHelper _urlHelper)
{
    lms_client = client;
    urlHelper = _urlHelper;
}

public PackagesController()
{
    lms_client = new LMS_ServiceClient();
    urlHelper = new UrlHelper(Request.RequestContext);
}

[HttpPost]
public ActionResult EditPackageDetails(
    int packageID,
    string package_name,
    int unit_type,
    int product_id,
    int unit_count,
    string description
    )
{
    lms_client.EditPackageDetails(
        packageID,
        package_name,
        unit_type,
        product_id,
        unit_count,
        description);
        
    var url = urlHelper.Action("PackagesList", "Packages");

    return Json(new
    {
        statusCode = (int)HttpStatusCode.OK,
        redirectURL = url
    });
}

urlBuilder.Action("PackagesList", "Packages"); 在测试运行期间返回 null。我试图通过将UrlHelper 类分配给控制器来伪造带有假返回值的类,但它似乎不起作用。这是我的测试的当前实现:

private readonly PackagesController _controller_Packages;
private readonly ILMS_Service _lms_service;

private readonly HttpContextBase httpContext;
private readonly HttpResponseBase httpResponse;
private readonly HttpSessionStateBase httpSession;
private readonly UrlHelper urlBuilder;

public Packages_UnitTest()
{
    // Mock WCF
    _lms_service = A.Fake<ILMS_Service>();

    // Fake session
    httpContext = A.Fake<HttpContextBase>();
    httpResponse = A.Fake<HttpResponseBase>();
    httpSession = A.Fake<HttpSessionStateBase>();
    urlBuilder = A.Fake<UrlHelper>();
    
    //SUTs
    _controller_Packages = new PackagesController(_lms_service, urlHelper);

    A.CallTo(() => httpContext.Response).Returns(httpResponse);
    A.CallTo(() => httpContext.Session).Returns(httpSession);
}

[TestMethod]
public void should_EditPackageDetails()
{
    // Arrange
    int packageID = 1;
    string package_name = "Test package";
    int unit_type = 1;
    int product_id = 1;
    int unit_count = 10;
    string description = "Sample test description";

    int expected_statusCode = (int)HttpStatusCode.OK;
    string expected_page_destination = "/Packages/PackagesList";

    var context = new ControllerContext(new RequestContext(httpContext, new RouteData()), _controller_Packages);
    _controller_Packages.ControllerContext = context;

    A.CallTo(() => urlBuilder.Action("PackagesList", "Packages"))
        .Returns("/Packages/PackagesList");

    // Act
    _ = A.CallTo(() => _lms_service.EditPackageDetails(
        A<int>.Ignored,
        A<string>.Ignored,
        A<int>.Ignored,
        A<int>.Ignored,
        A<int>.Ignored,
        A<string>.Ignored
        ));

    var _editPackage = _controller_Packages.EditPackageDetails(
        packageID,
        package_name,
        unit_type,
        product_id,
        unit_count,
        description
        ) as JsonResult;

    dynamic result = _editPackage.Data;

    // Assert
    Assert.AreEqual(expected_statusCode, result.statusCode);
    Assert.AreEqual(expected_page_destination, result.redirectURL);
}

通过这个测试,它仍然返回 null,而不是 "/Packages/PackagesList"。我如何伪造UrlHelper 并返回"/Packages/PackagesList" 作为FakeitEasy 的值?任何帮助,将不胜感激。我有一个 ASP.NET MVC 4、MSTest 和 FakeitEasy 模拟框架。谢谢!

【问题讨论】:

  • 顺便说一句:你一半配置_lms_service.EditPackageDetails。这不是您的问题的原因,但我认为这没有任何作用,并且该调用会分散测试中有用代码的注意力。

标签: c# asp.net-mvc mstest fakeiteasy


【解决方案1】:

假的UrlHelper 对我来说看起来不错,但你没有在EditPackageDetails 中使用它。您正在使用您构建的新UrlHelper

var urlBuilder = new UrlHelper(Request.RequestContext);

请改用_controller_Packages.Url

以及对未来的提示:调试测试通常会有所帮助。检查您使用的您认为可能是假货的值,看看它们是否真的是假货。

【讨论】: