c# - 如何对 POST 方法进行单元测试

标签 c# unit-testing

我在测试 post 方法时遇到问题。 在该方法中,检查了 AntiForgeryToken,我不知道如何模拟它。 除此之外,一切正常。

这是我想测试的方法:

[HttpPost]
    //[ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include="Id,Name,Manufacturer,CatalogNo")] Device device)
    {
        ValidateRequestHeader(Request);
        if (String.IsNullOrWhiteSpace(device.Name)||String.IsNullOrWhiteSpace(device.Manufacturer)||String.IsNullOrWhiteSpace(device.CatalogNo))
        {
            ModelState.AddModelError("", "Niepoprawne dane");
            return PartialView(device);
        }
        unitOfWork.deviceRepository.Insert(device);
        unitOfWork.Save();
        return Json(new { ok = true, newurl = Url.Action("Index") });
    }

我已经 mock 过:

        private IUnitOfWork fakeRepo;
    DeviceController DC;
    [TestInitialize]
    public void Initialize()
    {
        Mock<IUnitOfWork> mock = new Mock<IUnitOfWork>();
        mock.Setup(m => m.deviceRepository.Get(
            It.IsAny<List<Expression<Func<Device, bool>>>>(),
            It.IsAny<Func<IQueryable<Device>, IOrderedQueryable<Device>>>(),
            null))
            .Returns(new[] { new Device { Id = 1, Manufacturer = "a", Name = "b", CatalogNo = "x" } });
        mock.Setup(m => m.deviceRepository.Get()).Returns(new[] { new Device { Id = 1, Manufacturer = "a", Name = "b", CatalogNo = "z" } });
        fakeRepo = mock.Object;
        DC = new DeviceController(fakeRepo);
    }

但我不知道如何测试 AntiforgeryToken 这里的代码:

public void ValidateRequestHeader(HttpRequestBase request)
    {
        string cookieToken = "";
        string formToken = "";

        if (request.Headers["RequestVerificationToken"] != null)
        {
            string[] tokens = request.Headers["RequestVerificationToken"].Split(':');
            if (tokens.Length == 2)
            {
                cookieToken = tokens[0].Trim();
                formToken = tokens[1].Trim();
            }
        }
        AntiForgery.Validate(cookieToken, formToken);
    }

我无法注释掉这个调用测试目的,但这个解决方案看起来有点难看。

您能提出任何修改建议吗?

最佳答案

看来您需要模拟 HttpRequestBaseAntiForgery

How do you mock them?

您将它们包装在自己的界面中,公开您需要或在不久的将来可能需要的行为。在您的生产代码中,您提供真正的 .NET 实现,在您的测试中,您的模拟。

MSDN 说 AntiForgery.Validate

Validates that input data from an HTML form field comes from the user who submitted the data.

signature that takes two string arguments返回void .

你的模拟IAntiForgeryValidator会有 Validate(string, string)方法也返回 void。

public interface IAntiForgeryValidator
{
    void Validate(string cookieToken, string formToken);
}

public class AntiForgeryValidator : IAntiForgeryValidator
{
    public void Validate(string cookieToken, string formToken)
    {
        AntiForgery.Validate(cookieToken, formToken);
    }
}

您可以对 void 方法使用回调并验证它们被调用的次数是否正确:

antiForgeryMock.Setup(m => m.Validate(
        It.IsAny<string>(),
        It.IsAny<string>()))
        .Callback((string cookieToken, string formToken) =>
                            {
                                // call back
                            });

antiForgeryMock.Verify(m => m.Validate(
        It.IsAny<string>(),
        It.IsAny<string>()), Times.Once());

您还有另一个选择(作弊),那就是将您的调用 stub 到 ValidateRequestHeader()Create() 。这将使您能够测试其余代码,但不推荐,因为真正的 ValidateRequestHeader()如果您不测试该方法,可能会在您的生产代码中造成问题。

关于c# - 如何对 POST 方法进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22399570/

相关文章:

unit-testing - ActionScript 的可靠模拟框架?

c# - FluentValidation 中依赖规则的顺序

java - 是否可以在 Java 哈希表中添加没有值的键?

使用 Maven 运行时会跳过 Spring 测试

javascript - 如何使用 Jest 和 enzyme 测试异步数据获取 react 组件?

c# - 集成测试导致 Entity Framework 超时

c# - 使用 web.config 中的 httpRedirect 将 asp.net MVC URL 重定向到特定的 Controller /操作/参数

c# - 从 C# 进程调用 Accurev "hist"

c# - ‘finally’ block 可以更改其 ‘try’ block 的返回值吗?

c# - 检查微软组件是否存在