C# 用Ninject模拟标准内核接口
我正在使用Moq和Ninject.MockingKernal将单元测试添加到一些遗留ASP代码中C# 用Ninject模拟标准内核接口,c#,unit-testing,ninject,moq,C#,Unit Testing,Ninject,Moq,我正在使用Moq和Ninject.MockingKernal将单元测试添加到一些遗留ASP代码中 public class BaseController : Controller { private IAuthenticationManager authenticationManager; public ILog log; public BaseController() { var kern
public class BaseController : Controller
{
private IAuthenticationManager authenticationManager;
public ILog log;
public BaseController()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
log = kernel.Get<ILog>();
}
}
我试图模拟从内核设置的日志实例。此日志由其他控制器继承,不会被注入。我希望能够在请求时返回一个模拟对象,就像在其他情况下(例如从工厂返回模拟DatabaseContext)一样
我已经看过这个和GitHub示例,以及其他许多示例
根据我收集的信息,我需要按照以下思路做一些事情:
mockingKernal = new MoqMockingKernel();
mockingKernal.Bind<ILog>().To<Logging.Log>();
var foo = mockingKernal.GetMock<ILog>();
foo.Setup(x => x.Create(It.IsAny<AuditAction>(), It.IsAny<long>(), It.IsAny<string>()));
然而,如果我运行这个,我会得到一个错误System.ArgumentException:对象实例不是由Moq创建的。从我在网上看到的情况来看,这是由于类在构造函数中有一个参数造成的,但在本例中,Log类没有
我是否以正确的方式处理这个问题?如果我是,我做错了什么?任何帮助都将不胜感激上述方法/设计将导致各种各样的头痛来维护/测试,因为控制器与内核IoC容器紧密耦合,这基本上不允许人们能够轻松地模拟/替换它进行测试 还要注意的是,有问题的链接示例都有一个共同点,即能够显式地将依赖项注入测试对象中 以上内容基本上是将内核用作服务定位器 试着在口红上涂口红可能会改变它的外观,但对气味没有任何影响。 理想情况下,设计应遵循明确的原则 方法和类应该明确地要求通常通过方法参数或构造函数参数来实现它们正确运行所需的任何协作对象 这将允许对依赖项进行模拟/伪造/存根,并将其注入依赖项
//Arrange
var logger = new Mock<ILog>();
logger
.Setup(_ => _.Create(It.IsAny<AuditAction>(), It.IsAny<long>(), It.IsAny<string>()))
.Return(new AuditTrail);
var controller = new BaseController(logger.Object, null);
//Act
//...
不应该直接在类内调用容器,而应该在组合根处配置它
我建议审查当前的设计并相应地进行重构
public class BaseController : Controller {
private IAuthenticationManager authenticationManager;
public ILog log;
public BaseController(ILog log, IAuthenticationManager authenticationManager) {
this.log = log;
this.authenticationManager = authenticationManager;
}
}
//Arrange
var logger = new Mock<ILog>();
logger
.Setup(_ => _.Create(It.IsAny<AuditAction>(), It.IsAny<long>(), It.IsAny<string>()))
.Return(new AuditTrail);
var controller = new BaseController(logger.Object, null);
//Act
//...