如何Mock自定义ILoggerManager进行单元测试并验证LogError调用
首先得明确:咱们自己定义的ILoggerManager是业务抽象层,和框架自带的ILogger不一样,验证起来反而更直接——不需要去拆解底层Log方法的复杂参数,直接针对我们的接口方法做验证就行。
针对你的场景,具体操作如下:
准备Mock对象
你已经创建了ILoggerManager<A>的Mock实例,这一步没问题:var loggerMock = new Mock<ILoggerManager<A>>();注入并执行测试方法
把Mock对象注入到类A的实例中,然后调用Test()方法:var service = ServiceFactory.Create<A>(loggerMock); service.Test();验证LogError的调用
直接用Mock的Verify方法,检查LogError是否被调用了一次,并且参数匹配你的测试消息。这里要注意你的LogError方法签名是LogError(string message, LoggerErrorType type),但类A里调用的是LogError("test message")——如果是存在带默认参数的重载,或者你调用时省略了默认值,那验证代码要对应上:情况1:类A调用的是带两个参数的重载(含默认参数)
// 验证LogError被调用了一次,消息是"test message",错误类型匹配默认值(比如LoggerErrorType.Default) loggerMock.Verify( lm => lm.LogError("test message", It.IsAny<LoggerErrorType>()), // 若知道默认值,也可以替换成具体值 Times.Once, "LogError方法未被正确调用,或者参数不匹配" );情况2:类A调用的是仅含string参数的重载
如果你的
ILoggerManager有LogError(string message)的重载,那验证代码更简单:loggerMock.Verify( lm => lm.LogError("test message"), Times.Once, "LogError方法未被正确调用,或者消息不匹配" );
为什么不用之前ILogger的验证方式?
之前验证ILogger是因为它的Log方法是框架定义的,参数复杂;但ILoggerManager是咱们自己的抽象,单元测试的核心是验证类A和依赖的抽象层之间的交互是否正确,不需要关心ILoggerManager内部到底是用ILogger还是NLog实现的——那是LoggerManager类自己的单元测试要关心的事情。
举个例子:如果以后你把LoggerManager里的NLog换成Serilog,类A的单元测试完全不需要修改,因为我们依赖的是抽象而非具体实现,这也是依赖注入的优势之一。
内容的提问来源于stack exchange,提问作者Gavin.Sun

