【问题标题】:Expected invocation on the mock once, but was 0 times No invocations performed预期在模拟上调用一次,但为 0 次 未执行调用
【发布时间】:2014-03-17 08:10:41
【问题描述】:

我正在尝试模拟如下函数:

AntiForgeryValidator a = new AntiForgeryValidator();
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();
        }
    }
    a.Validate(cookieToken, formToken);
    //AntiForgery.Validate(cookieToken, formToken);
}

于是我创建了界面:

public interface IAntiForgeryValidator
{
    //void ValidateRequestHeader(HttpRequestBase request);
    void Validate(string cookieToken, string formToken);
}
public class AntiForgeryValidator : IAntiForgeryValidator
{
    public void Validate(string cookieToken, string formToken)
    {
        AntiForgery.Validate(cookieToken, formToken);
    }
}

并将新代码添加到测试项目中: 模拟 Http 请求:

Mock<HttpRequestBase> Request = new Mock<HttpRequestBase>();
Request.SetupGet(x => x.Headers).Returns(new System.Net.WebHeaderCollection{
    {"RequestVerificationToken", "RequestVerificationToken"}
});

和模拟验证方法:

Mock<IAntiForgeryValidator> antiForgeryMock = new Mock<IAntiForgeryValidator>();
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());

这是我使用此页面上找到的答案设法创建的所有代码。 但我仍然在主题中遇到错误。 我想这一切都是由这行引起的:

.Callback((string cookieToken, string formToken) =>
        {
            // call back
        });

但我不知道应该放什么。阅读 Moq 文档也无济于事。

@更新: 尝试像创建 fakeRepository 一样这样做

private IAntiForgeryValidator fakeValidation;
fakeValidation = antiForgeryMock.Object;

我尝试触发测试时的功能:

[TestMethod]
public void EditPost()
{
    var data = default(Device);
    var result = DC.Edit(data);
    Assert.IsNotNull(result);
}

@更新二: 添加新代码:

DC.ControllerContext = new ControllerContext(context.Object,new RouteData(),DC);

现在如果我注释掉 Veryfy 代码可以工作并传递给控制器​​。但仍然无法在未注释的情况下工作

【问题讨论】:

  • 如何将 mock 传递给您正在测试的对象?
  • 由于 AntiForgeryValidator.Validate 只被调用一次并返回 void,因此您可能没有什么理由想要在其上调用 Setup,因为您可以通过 Verify 调用。但是,我从来没有发现调用Setup() 会干扰Mock.Verify,所以我不认为是这样。根据Sergey,请显示var sut = new ValidateRequestHeader(antiForgeryMock.Object);sut.ValidateRequestHeader(fakeRequest)等代码
  • 我用你问的代码更新了问题

标签: c# asp.net-mvc unit-testing moq


【解决方案1】:

您必须在运行测试操作后放置 antiForgeryMock.Verify()。测试通常如下所示:

// arrange
var myMock = new Mock<MyInterface>();
myMock.Setup(...);
var mySut = new Sut(myMock.Object);

// act
mySut.DoSomething()

//assert
myMock.Verify(...);

如 cmets 中所述,您的测试不需要设置,因此您将跳过该部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-06
    • 2021-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多