场景
我想检查某个组件(sut)在特定情况下是否记录错误。将ILogger接口构造函数注入到组件中,并且Error方法具有4个重载。
因此,我在Arrange中创建了一个ILogger模拟,并在Act中使用了它。
我不应该期望sut正在使用哪个过载,只是希望期望并检查是否调用了任何过载。 (那将是白盒,并且期望远远超出功能规格。)
问题
目前,我的结论是我不能使用.Received
,而必须为所有4个重载安装回调,并在其中设置一个变量,然后在Assert部分中检查该变量。
有什么简单的方法可以做到这一点吗?
(示例)
[TestMethod]
public void ShouldLogErrorIfEmailIsInvalid2()
{
// Arrange
var testEmailAddress = "dummy";
//var mock = new Mock<IEMailValidator>();
var validator = Substitute.For<IEMailValidator>();
validator.Validate(Arg.Any<string>()).Returns(false);
var logger = Substitute.For<ILogger>();
var sut = new CustomerController(validator, logger);
var customer = new Customer() { Email = testEmailAddress };
// Act
sut.Post(customer);
// Assert
// *** Here I do not want to expect a specific overload of Error, instead any of the 4 overloads satisfies the expectation
logger.Received(1).Error(Arg.Is<string>( m => m.ToLower().Contains("email")), Arg.Any<object>());
}
答案 0 :(得分:2)
NSubstitute没有内置语法,但是可以查询所有ReceivedCalls()
并对此进行手动声明。
例如:
var errorCalls = logger.ReceivedCalls()
.Where(x => x.GetMethodInfo().Name == nameof(logger.Error))
.Where(x => (x.GetArguments()[0] as string).ToLower().Contains("email"));
Assert.AreEqual(1, errorCalls.Count());
如果这是您经常需要的东西,则可以实现一些辅助方法,并将其打包为我认为非常简洁的东西。 (也许static void ReceivedCallToAny(this object substitute, string methodName, Func<object[], bool> requiredArgs)
和T GetItemAs<T>(object[] items)
这样的助手可以访问参数?)