我在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,它从PageId
集合中提取ApplicationPagePermissions
属性并将其作为IEnumerable<string>
返回。因为该属性中的投影创建了一个新对象,所以替换不匹配,因为它将两个对象视为不同。
我可以在传递给GetMenuData
的参数上创建一个回调,以便我可以检查它的值吗?
NSubstitute callbacks上的文档仅讨论检查调用的返回值,而不是传递给调用的参数。
答案 0 :(得分: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);
}