Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using Autofac;
- using Autofac.Builder;
- using Moq;
- using System.Reflection;
- using Autofac.Component.Activation;
- using Autofac.Component;
- using Autofac.Component.Scope;
- namespace yellowbook.testing.common
- {
- /// <summary>
- /// Auto-mocking factory that can create an instance of the
- /// class under test and automatically inject mocks for all its dependencies.
- /// </summary>
- /// <remarks>
- /// Note that only interface dependencies will be mocked for now.
- /// </remarks>
- public class AutoMockContainer : IResolve
- {
- IContainer container;
- MockFactory factory;
- /// <summary>
- /// Initializes the container with the <see cref="MockFactory"/> that
- /// will be used to create dependent mocks.
- /// </summary>
- public AutoMockContainer(MockFactory factory)
- {
- this.factory = factory;
- var builder = new ContainerBuilder();
- builder.Register(this).OwnedByContainer();
- this.container = builder.Build();
- this.container.AddRegistrationSource(new MoqRegistrationSource(this.factory));
- }
- /// <summary>
- /// Gets or creates a mock for the given type, with
- /// the default behavior specified by the factory.
- /// </summary>
- public Mock<T> GetMock<T>()
- where T : class
- {
- // TODO: support passing a different MockBehavior ?
- var obj = (IMocked<T>)this.Create<T>();
- return obj.Mock;
- }
- /// <summary>
- /// Creates an instance of a class under test,
- /// injecting all necessary dependencies as mocks.
- /// </summary>
- /// <typeparam name="T">Requested object type.</typeparam>
- public T Create<T>() where T : class
- {
- if (!container.IsRegistered<T>())
- {
- var builder = new ContainerBuilder();
- builder.Register<T>();
- builder.Build(container);
- }
- return container.Resolve<T>();
- }
- /// <summary>
- /// Creates an instance of a class under test using
- /// the given activator function.
- /// </summary>
- /// <typeparam name="T">Requested object type.</typeparam>
- public T Create<T>(Func<IResolve, T> activator) where T : class
- {
- if (!container.IsRegistered<T>())
- {
- var builder = new ContainerBuilder();
- builder.Register<T>(c => activator(this));
- builder.Build(container);
- }
- return container.Resolve<T>();
- }
- /// <summary>
- /// Registers and resolves the given service on the container.
- /// </summary>
- /// <typeparam name="TService">Service</typeparam>
- /// <typeparam name="TImplementation">The implementation of the service.</typeparam>
- public void Register<TService, TImplementation>()
- {
- var builder = new ContainerBuilder();
- builder.Register<TImplementation>().As<TService>().ContainerScoped();
- builder.Build(container);
- // TODO: why would you need back the instance you have just registered?
- // Isn't it supposed to be automatically injected from now on?
- //return Resolve<TService>();
- }
- /// <summary>
- /// Registers the given service instance on the container.
- /// </summary>
- /// <typeparam name="TService">Service type.</typeparam>
- /// <param name="instance">Service instance.</param>
- public void Register<TService>(TService instance)
- {
- var builder = new ContainerBuilder();
- builder.Register(instance).As<TService>();
- builder.Build(container);
- }
- /// <summary>
- /// Registers the given service creation delegate on the container.
- /// </summary>
- /// <typeparam name="TService">Service type.</typeparam>
- public void Register<TService>(Func<IResolve, TService> activator)
- {
- var builder = new ContainerBuilder();
- builder.Register(c => activator(this)).As<TService>();
- builder.Build(container);
- }
- /// <summary>
- /// Resolves a required service of the given type.
- /// </summary>
- public T Resolve<T>()
- {
- return container.Resolve<T>();
- }
- /// <summary>
- /// Resolves unknown interfaces and Mocks using
- /// the <see cref="MockFactory"/> from the scope.
- /// </summary>
- class MoqRegistrationSource : IRegistrationSource
- {
- private readonly MockFactory factory;
- private readonly MethodInfo createMethod;
- public MoqRegistrationSource(MockFactory factory)
- {
- this.factory = factory;
- this.createMethod = factory.GetType().GetMethod("Create", new Type[] { });
- }
- /// <summary>
- /// Retrieve a registration for an unregistered service, to be used
- /// by the container.
- /// </summary>
- /// <param name="service">The service that was requested.</param>
- /// <param name="registration">A registration providing the service.</param>
- /// <returns>
- /// True if the registration could be created.
- /// </returns>
- public bool TryGetRegistration
- (Service service, out IComponentRegistration registration)
- {
- if (service == null)
- throw new ArgumentNullException("service");
- registration = null;
- var typedService = service as TypedService;
- if ((typedService == null) || (!typedService.ServiceType.IsInterface))
- return false;
- var descriptor = new Descriptor(
- new UniqueService(),
- new[] { service },
- typedService.ServiceType);
- registration = new Registration(
- descriptor,
- new DelegateActivator
- ((c, p) =>
- {
- var specificCreateMethod = this.createMethod.MakeGenericMethod(new[] { typedService.ServiceType });
- var mock = (Mock)specificCreateMethod.Invoke(factory, null);
- return mock.Object;
- }),
- new ContainerScope(),
- InstanceOwnership.Container);
- return true;
- }
- }
- }
- /// <summary>
- /// Interface implemented by the <see cref="AutoMockContainer"/> so that
- /// the <c>Register</c> overloads can receive a creation
- /// function for the service, rather than just a type.
- /// </summary>
- public interface IResolve
- {
- /// <summary>
- /// Resolves a required service of the given type.
- /// </summary>
- T Resolve<T>();
- }
- }
Add Comment
Please, Sign In to add comment