Verifying a call parameter via a callback in NSubstitute

c#, callback, mocking, nsubstitute, unit-testing

Solution

Typical. As soon as I post to SO, the answer presents itself. Rather than expecting a specific object when creating the substitute call, I expect any instance of type `IEnumerable<string>` and create a callback when checking the `Received()` call that actually verifies the values. The substitute call becomes this:

MenuDataProviderSub.GetMenuData(Arg.Any<IEnumerable<string>>()).Returns(Arg.Any<IList<BusinessFocusArea>>());            

The `Received()` check becomes this:

MenuDataProviderSub.Received().GetMenuData(Arg.Is<IEnumerable<string>>(a => VerifyPageIds(ExpectedUserPermissions.AuthorisedPageIds, a)));

private static bool VerifyPageIds(IEnumerable<string> expected, IEnumerable<string> actual)
{
    var expectedIds = expected.ToList();
    var actualIds = actual.ToList();
    return expectedIds.Count == actualIds.Count && expectedIds.All(actualIds.Contains);
}

Problem

I have a failing test in NSubstitute because a parameter passed in to a substituted call does not match. Here is the relevant code that is being tested: ``` // Arrange PermissionsProviderSub = Substitute.For<IPermissionsProvider>(); MenuDataProviderSub = Substitute.For<IMenuDataProvider>(); PermissionsProviderSub.GetPermissions(UserId).Returns(ExpectedUserPermissions); MenuDataProviderSub.GetMenuData(ExpectedUserPermissions.AuthorisedPageIds).Returns(Arg.Any<IList<BusinessFocusArea>>()); var sut = new MenuViewModelFactory(MenuDataProviderSub, PermissionsProviderSub); // Act var result = sut.Create(); // Assert MenuDataProviderSub.Received().GetMenuData(ExpectedUserPermissions.AuthorisedPageIds); ``` The problem occurs in the `ExpectedUserPermissions.AuthorisedPageIds` property, which looks like this: ``` public IEnumerable<string> AuthorisedPageIds { get { return ApplicationPagePermissions != null ? ApplicationPagePermissions.Select(permissionSet => permissionSet.PageId) : Enumerable.Empty<string>(); } } ``` As you can see, there is a LINQ Select, which is extracting the `PageId` property from within the `ApplicationPagePermissions` collection and returning it as an `IEnumerable<string>`. Because the projection within that property creates a new object, the substitution does not match, as it sees the 2 objects as being different. Can I create a callback on the parameter passed in to `GetMenuData` so that I can examine the value of it? The documentation on NSubstitute callbacks only talks about examining the return value from a call, rather than a parameter passed into the call.

Original source

Related problems