如何单元测试POST方法

时间:2014-03-14 08:20:09

标签: 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") });
    }

我已经嘲笑过:

        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);
    }

我无法评论此通话测试目的,但此解决方案似乎有些难看。

你能建议任何编辑吗?

1 个答案:

答案 0 :(得分:2)

您似乎需要模拟HttpRequestBaseAntiForgery

  

你怎么嘲笑他们?

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

MSDN说AntiForgery.Validate

  

验证来自HTML表单字段的输入数据来自用户   谁提交了数据。

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());

您还有其他选择(作弊),那就是将您的来电存根到ValidateRequestHeader()中的Create()。这将使您能够测试其余代码但不会被推荐,因为如果您不对此方法进行测试,真正的ValidateRequestHeader()可能会导致您的生产代码出现问题。