g.p*_*dou 3 unit-testing mocking nsubstitute
设想
我想检查一个组件(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>());
}
Run Code Online (Sandbox Code Playgroud)
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());
Run Code Online (Sandbox Code Playgroud)
如果这是您经常需要的东西,您可以实现一些辅助方法并将其打包成我认为相当简洁的东西。(也许static void ReceivedCallToAny(this object substitute, string methodName, Func<object[], bool> requiredArgs)有些助手喜欢T GetItemAs<T>(object[] items)访问参数?)