-1

Im using FakeItEasy to mock methods for unit tests. One of method (using REF parameter - maybe this is important) saves data in database, so it's mocked as 'Does Nothing'

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

. But in this situation last assert fails

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

with error:

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)

Full code of test

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

UPDATE 1:

Please notice that for both calls to this method Save, value of mwbeUserData is the same

MwbeUserData mwbeUserData = mwbeReturnData.Data;

If this is null (but it's not).

Maybe the is problem with syntax for REF parameter? I read that there should be used method called AssignsOutAndRefParameters, but I dont know exactly how to use it.

For now I will use MATCHES parameter to make it more generic.

P.K.
  • 1,746
  • 6
  • 25
  • 62

1 Answers1

3

I believes that it's occurred because you assert against mwbeUserData instance

@Old Fox has the right of it.

You're asking FakeItEasy if mockedUserRepository.Save(ref mwbeUserData) was called with null input (mwbeUserData must be null at the time you make the check). It saw nothing like that, since the MwbeUserData that was passed to mockedUserRepository.Save inside AddUser appears to have been not null.

If you think the test should've passed, perhaps relaxing your constraint will help, as in FakeItEasy: mocked method is not returning expected result.

Also, note that the refness of the parameter has no effect on this behaviour. the same constraint matching would occur for a "plain" parameter. Only out parameters are exempted by default. See Argument Constraints in the FakeItEasy documentation for more information about this, and more on how to use custom argument matchers.

Community
  • 1
  • 1
Blair Conrad
  • 233,004
  • 25
  • 132
  • 111
  • 1
    At Blair Conraid: I understand your idea, because it was my first post about FakeItEasy :) – P.K. Aug 19 '15 at 05:55
  • Nice answer +1, this is what I thought in the first look but then I read again the question and I saw the exception, based on the exception there are 4 options: 1.in `AddUser` the OP initialize a new instance which he saves(if so he has a bug, the code should throw Null Reference...). 2.in `AddUser` the OP do null validation before he saves the object. 3.Special flow in `AddUser`. 4. I need a new glasses :) So we need the `AddUser` implementation to figure out the correct reason. – Old Fox Aug 19 '15 at 17:16