AutoMockContainer,支持具有非接口依赖性的自动锁定类

我有一个具有非接口依赖的构造函数:

public MainWindowViewModel(IWorkItemProvider workItemProvider, WeekNavigatorViewModel weekNavigator) 

我正在使用Moq.Contrib automockcontainer。 如果我尝试自动锁定MainWindowViewModel类,由于WeekNavigatorViewModel依赖项,我收到错误。

是否有任何automocking容器支持非接口类型的模拟?

正如马克在下面所示; 是的你可以! :-)我将Moq.Contrib AutoMockContainer替换为Mark在他的答案中提出的东西,唯一的区别是自动生成的模拟被注册为单例,但你可以使这个可配置。 这是最终的解决方案:

 ///  /// Auto-mocking factory that can create an instance of the /// class under test and automatically inject mocks for all its dependencies. ///  ///  /// Mocks interface and class dependencies ///  public class AutoMockContainer { readonly IContainer _container; public AutoMockContainer(MockFactory factory) { var builder = new ContainerBuilder(); builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource()); builder.RegisterSource(new MoqRegistrationSource(factory)); _container = builder.Build(); } ///  /// Gets or creates a mock for the given type, with /// the default behavior specified by the factory. ///  public Mock GetMock() where T : class { return (_container.Resolve() as IMocked).Mock; } ///  /// Creates an instance of a class under test, /// injecting all necessary dependencies as mocks. ///  /// Requested object type. public T Create() where T : class { return _container.Resolve(); } public T Resolve() { return _container.Resolve(); } ///  /// Registers and resolves the given service on the container. ///  /// Service /// The implementation of the service. public void Register() { var builder = new ContainerBuilder(); builder.RegisterType().As().SingleInstance(); builder.Update(_container); } ///  /// Registers the given service instance on the container. ///  /// Service type. /// Service instance. public void Register(TService instance) { var builder = new ContainerBuilder(); if (instance.GetType().IsClass) builder.RegisterInstance(instance as object).As(); else builder.Register(c => instance).As(); builder.Update(_container); } class MoqRegistrationSource : IRegistrationSource { private readonly MockFactory _factory; private readonly MethodInfo _createMethod; public MoqRegistrationSource(MockFactory factory) { _factory = factory; _createMethod = factory.GetType().GetMethod("Create", new Type[] { }); } public IEnumerable RegistrationsFor(Service service, Func<Service, IEnumerable> registrationAccessor) { var swt = service as IServiceWithType; if (swt == null) { yield break; } if (!swt.ServiceType.IsInterface) yield break; var existingReg = registrationAccessor(service); if (existingReg.Any()) { yield break; } var reg = RegistrationBuilder.ForDelegate((c, p) => { var createMethod = _createMethod.MakeGenericMethod(swt.ServiceType); return ((Mock)createMethod.Invoke(_factory, null)).Object; }).As(swt.ServiceType).SingleInstance().CreateRegistration(); yield return reg; } public bool IsAdapterForIndividualComponents { get { return false; } } } } 

如果您利用支持即时解析所请求类型的DI容器 ,您可以很容易地自己编写一个。

我最近使用Autofac和Moq为这个目的编写了一个原型,但是可以使用其他容器。

这是适当的IRegistrationSource:

 public class AutoMockingRegistrationSource : IRegistrationSource { private readonly MockFactory mockFactory; public AutoMockingRegistrationSource() { this.mockFactory = new MockFactory(MockBehavior.Default); this.mockFactory.CallBase = true; this.mockFactory.DefaultValue = DefaultValue.Mock; } public MockFactory MockFactory { get { return this.mockFactory; } } #region IRegistrationSource Members public IEnumerable RegistrationsFor( Service service, Func> registrationAccessor) { var swt = service as IServiceWithType; if (swt == null) { yield break; } var existingReg = registrationAccessor(service); if (existingReg.Any()) { yield break; } var reg = RegistrationBuilder.ForDelegate((c, p) => { var createMethod = typeof(MockFactory).GetMethod("Create", Type.EmptyTypes).MakeGenericMethod(swt.ServiceType); return ((Mock)createMethod.Invoke(this.MockFactory, null)).Object; }).As(swt.ServiceType).CreateRegistration(); yield return reg; } #endregion } 

您现在可以在unit testing中设置容器,如下所示:

 [TestMethod] public void ContainerCanCreate() { // Fixture setup var builder = new ContainerBuilder(); builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource()); builder.RegisterSource(new AutoMockingRegistrationSource()); var container = builder.Build(); // Exercise system var result = container.Resolve(); // Verify outcome Assert.IsNotNull(result); // Teardown } 

这就是你开始所需要的一切。

MyClass是一个具有抽象依赖的具体类。 这是构造函数签名:

 public MyClass(ISomeInterface some) 

请注意,您不必在生产代码中使用Autofac(或任何其他DI容器)。