【问题标题】:How do I verify a method was called?如何验证方法是否被调用?
【发布时间】:2011-12-25 12:45:44
【问题描述】:

我有一个依赖于ITicketApiAdapter 的ICreateService 类。我尝试注册一个模拟 ITicketAdaper,以便在我创建匿名创建服务时注入它。

所以,在设置中,我有这个用于票证适配器的寄存器:

Fixture.Register(() =>
    {
        var ticketApiAdapter = new Mock<ITicketApiAdapter>();
        ticketApiAdapter
            .Setup( x => x.AddTicketComment(
                It.IsAny<User>(), 
                It.IsAny<Customer>(), 
                It.IsAny<TicketComment>()))
        .Returns(new SaveResult
                        {
                            Success = true, 
                            Id = Fixture.CreateAnonymous<Guid>().ToString()
                        });

        return ticketApiAdapter;
    });

Fixture.Register(() => new CreateService(Fixture.CreateAnonymous<Mock<ITicketApiAdapter>>().Object));

据我了解,这应该“冻结”ICreateService 和 Mock&lt;ITicketApiAdapter&gt;,这样当我请求匿名实例时,它就是我注册的实例。

我有一个看起来像这样的测试:

[TestMethod]
public void CreateServiceCallsAddTicketComment()
{
    var apiTicketAdapter = Fixture.CreateAnonymous<Mock<ITicketApiAdapter>>();
    var createTicketRequest = Fixture.CreateAnonymous<CreateTicketComment>();
    var createService = Fixture.CreateAnonymous<CreateService>();

    var results = createService.CreateTicketComment(createTicketRequest);

    apiTicketAdapter
        .Verify(x => x.AddTicketComment(
            It.IsAny<User>(), 
            It.IsAny<Customer>(), 
            It.IsAny<TicketComment>()), 
        Times.Once());

    Assert.IsTrue(results.All(x => x.Success));
    Assert.IsTrue(results.All(x => x.Errors.Count == 0));

}

我希望 apiTicketAdapter 是我注册的那个,以便我可以验证该方法是否被调用。如果我单步执行,则会调用 TicketApiAdapter,但 Moq 说没有。

编辑

这是我得到的错误:

CreateServiceCallsAddTicketComment 抛出异常: Moq.MockException:预期在模拟上调用一次,但为 0 次:x => x.AddTicketComment(It.IsAny(), It.IsAny(), It.IsAny())

配置设置:x => x.AddTicketComment(It.IsAny(), It.IsAny()、It.IsAny())、Times.Never 否 执行的调用。

【问题讨论】:

  • 显示起订量的确切信息是什么?
  • @Serghei 添加了错误信息
  • 请添加AddTicketComment()方法的代码
  • 它在第一个代码块中。这只是一个返回良好结果的模拟。
  • 我不明白为什么你希望在 x.AddTicketComment() 中调用 AddTicketComment() 方法,如果你根本没有在这个方法中调用它,你没有实现你我正确理解的 CreateSerice。正如我在 CreateService 类中所理解的那样,您应该有方法 x.AddTicketComment() 并且该方法应该调用 AddTicketComment() ?你能展示一下 CreateService 的实现吗?

标签: c# unit-testing moq autofixture


【解决方案1】:

当您注册一个代码块时,该代码块将被调用每次 Fixture 实例解析请求的类型。这意味着它没有被冻结。如果你想冻结某些东西,Freeze overloads 之一通常更容易使用。

更好的是,既然您似乎在使用 Moq,我可以建议使用 AutoMoq extension 吗?

这将使您能够将测试重写为以下内容:

[TestMethod]
public void CreateServiceCallsAddTicketComment(new AutoMoqCustomization());
{
    var fixture = new Fixture().Customize()
    var apiTicketAdapter = fixture.Freeze<Mock<ITicketApiAdapter>>();
    ticketApiAdapter
        .Setup( x => x.AddTicketComment(
            It.IsAny<User>(), 
            It.IsAny<Customer>(), 
            It.IsAny<TicketComment>()))
        .Returns(new SaveResult
        {
            Success = true, 
            Id = Fixture.CreateAnonymous<Guid>().ToString()
        });

    var createTicketRequest = fixture.Freeze<CreateTicketComment>();
    var createService = fixture.CreateAnonymous<CreateService>();

    var results = createService.CreateTicketComment(createTicketRequest);

    apiTicketAdapter
        .Verify(x => x.AddTicketComment(
            It.IsAny<User>(), 
            It.IsAny<Customer>(), 
            It.IsAny<TicketComment>()), 
        Times.Once());

    Assert.IsTrue(results.All(x => x.Success));
    Assert.IsTrue(results.All(x => x.Errors.Count == 0));

}

假设 CreateTicketRequest 使用构造函数注入或属性注入。

【讨论】:

  • 谢谢马克。我一直在阅读您的博客,但我似乎无法完全了解 AutoFixture/AutoMoq 功能。简单的测试似乎很容易,但我缺少的是完整的设置。我希望能够设置apiTicketAdapter 一次,然后测试CreateService 中的所有方法正在调用适配器上的不同方法。如果我在[TestSetup] 中释放票证适配器,我可以在每个[TestMehtod] 中使用 Freeze 来获取相同的实例来验证方法是否已被调用?
  • 通过尝试回答了我自己的问题;)它似乎符合我的预期。附带说明一下,当我尝试从 Google 搜索结果访问您的博客时,Chrome 每次都会崩溃。
  • 代码示例的第 6 行,应该是 apiTicketAdaptor,而不是 ticketApiAdaptor?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-31
  • 1970-01-01
相关资源
最近更新 更多