【问题标题】:when mocked method with ref parameter is used, assert MustHaveHappened fails当使用带有 ref 参数的模拟方法时,断言 MustHaveHappened 失败
【发布时间】:2016-05-31 22:07:55
【问题描述】:

我正在使用 FakeItEasy 来模拟单元测试的方法。一种方法(使用 REF 参数 - 也许这很重要)将数据保存在数据库中,因此它被模拟为“什么都不做”

A.CallTo(() => mockedUserRepository.Save(ref mwbeUserData)).DoesNothing();

。但是在这种情况下,最后一个断言失败了

A.CallTo(() => mockedUserRepository.Save(ref mwbeUserData)).MustHaveHappened(Repeated.Exactly.Once);

有错误:

Assertion failed for the following call:
    MobileWallet.Common.DAL.IMwbeUserRepository.Save(<NULL>)
  Expected to find it exactly once but found it #0 times among the calls:
    1: MobileWallet.Common.DAL.IMwbeUserRepository.Get(userName: \"AAA\")
    2: MobileWallet.Common.DAL.IMwbeUserRepository.Save(user: MobileWallet.Common.Repository.MwbeUserData)

完整的测试代码

[TestMethod]
public void AddUser_MwbeUserObjectReturned()
{
    //Arrange

    MwbeUserRegistrationIn userRegistrationIn = new MwbeUserRegistrationIn()
    {
        BirthDate = DateTime.Today,
        Email = "www@wp.pl",
        FirstName = "Adam",
        SecondName = "Ada2",
        UserName = "AAA"
    };

    //mock mockedNotificationService and related: 
    INotificationService mockedNotificationService = A.Fake<INotificationService>();
    //TODO: create notofication service

    //mock IMwbeUserRepository and related
    IMwbeUserRepository mockedUserRepository = A.Fake<IMwbeUserRepository>();

    MwbeReturnData<MwbeUserData> mwbeReturnData = new MwbeReturnData<MwbeUserData>(MwbeResponseCodes.NotFound);          

    MwbeUserData mwbeUserData = mwbeReturnData.Data;

    A.CallTo(() => mockedUserRepository.Get(userRegistrationIn.UserName)).Returns(mwbeReturnData);
    A.CallTo(() => mockedUserRepository.Save(ref mwbeUserData)).DoesNothing();

    MwbeUserService userService = new MwbeUserService(mockedUserRepository, mockedNotificationService);

    //Act
    MwbeUser user = userService.AddUser(userRegistrationIn);

    //Assert
    Assert.IsNotNull(user);            
    Assert.AreEqual(userRegistrationIn.Email, user.Email);
    Assert.AreEqual(userRegistrationIn.UserName, user.UserName);
    Assert.AreEqual(userRegistrationIn.FirstName,user.FirstName);
    Assert.AreEqual(userRegistrationIn.SecondName, user.SecondName);
    Assert.AreEqual(userRegistrationIn.BirthDate, user.BirthDate);

    A.CallTo(() => mockedUserRepository.Get(userRegistrationIn.UserName)).MustHaveHappened(Repeated.Exactly.Once);
    A.CallTo(() => mockedUserRepository.Save(ref mwbeUserData)).MustHaveHappened(Repeated.Exactly.Once);
}

更新 1:

请注意,对于此方法 Save 的两次调用,mwbeUserData 的值是相同的

MwbeUserData mwbeUserData = mwbeReturnData.Data;

如果这是 null(但不是)。

也许 REF 参数的语法有问题?我读到应该使用名为 AssignsOutAndRefParameters 的方法,但我不知道如何使用它。

现在我将使用 MATCHES 参数使其更通用。

【问题讨论】:

  • 我认为这是因为您对mwbeUserData 实例进行断言...请添加AddUser 方法的代码..
  • 请添加AddUser实现

标签: unit-testing assert fakeiteasy


【解决方案1】:

我认为它的发生是因为您针对 mwbeUserData 实例断言

@Old Fox 拥有它的权利。

您是在询问 FakeItEasy 是否使用 null 输入调用了 mockedUserRepository.Save(ref mwbeUserData)(在您进行检查时,mwbeUserData 必须为空)。它什么也没看到,因为在AddUser 中传递给mockedUserRepository.SaveMwbeUserData 似乎不是空的。

如果您认为测试应该已经通过,也许放松您的约束会有所帮助,例如 FakeItEasy: mocked method is not returning expected result

另外,请注意参数的refness 对此行为没有影响。对于“普通”参数,将发生相同的约束匹配。默认情况下仅豁免 out 参数。请参阅 FakeItEasy 文档中的 Argument Constraints 了解更多信息,以及有关如何使用自定义参数匹配器的更多信息。

【讨论】:

  • 在 Blair Conraid:我理解你的想法,因为这是我关于 FakeItEasy 的第一篇文章 :)
  • 不错的答案 +1,这是我第一次看时的想法,但后来我再次阅读了这个问题,我看到了异常,基于异常有 4 个选项:1.in AddUser OP初始化一个他保存的新实例(如果他有一个错误,代码应该抛出空引用......)。 2.在AddUser OP 在保存对象之前进行空验证。 3.AddUser的特殊流量。 4. 我需要一副新眼镜 :) 所以我们需要AddUser 实现来找出正确的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-29
相关资源
最近更新 更多