5

我在 NSubstitute 中有一个失败的测试,因为传递给替换调用的参数不匹配。以下是正在测试的相关代码:

// 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);

问题出现在ExpectedUserPermissions.AuthorisedPageIds属性中,如下所示:

public IEnumerable<string> AuthorisedPageIds
{
    get
    {
        return ApplicationPagePermissions != null ? 
            ApplicationPagePermissions.Select(permissionSet => permissionSet.PageId) :
            Enumerable.Empty<string>();
    }
}

如您所见,有一个 LINQ Select,它PageIdApplicationPagePermissions集合中提取属性并将其作为IEnumerable<string>. 因为该属性中的投影创建了一个新对象,所以替换不匹配,因为它认为这 2 个对象是不同的。

我可以在传入的参数上创建一个回调,GetMenuData以便我可以检查它的值吗?

NSubstitute 回调的文档只讨论了检查调用的返回值,而不是传递给调用的参数。

4

1 回答 1

6

典型的。一旦我发布到 SO,答案就会出现。在创建替代调用时,我期望任何类型的实例并在检查实际验证值IEnumerable<string>的调用时创建回调,而不是期望特定对象。Received()替代调用变成了这样:

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

Received()支票变成了这样:

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);
}
于 2013-02-22T14:51:31.680 回答