How to mock autofac type registration? - c#

I have following registration in my autofac container:
builder.RegisterType<EmailService>().As<IEmailService>().InstancePerLifetimeScope();
builder.RegisterType<AzureBlobStorageService>().InstancePerLifetimeScope();
Some commands depend on these services. But in my tests I don't need them, it's not what I want to test.
So I tried to rewrite registrations in following way:
builder.RegisterType<Mock<EmailService>>().As<IEmailService>().InstancePerLifetimeScope();
builder.RegisterType<Mock<AzureBlobStorageService>>().InstancePerLifetimeScope();
But I'm getting error:
Message: System.ArgumentException : The type 'Moq.Mock 1[EmailService]' is not assignable to service 'Moq.Mock`1[[IEmailService, ...]]'.
How to do it proper way?

If you want to register a mock for the IEmailService interface, you could use the RegisterInstance method:
builder.RegisterInstance(new Mock<IEmailService>().Object)
.As<IEmailService>();

Related

Using LightInject, how can I register a generic service with a factory method?

I want to configure a logger that logs to xUnit test output, and should be substituted for all ILogger<T> dependencies. As far as I can tell, the way to solve this is to use a generic service with a factory method.
When using Microsoft.Extensions.DependencyInjection, I can do the following:
services.AddTransient(typeof(ILogger<>),
factory => factory.GetRequiredService<LoggerFactory>().CreateLogger("TestLogger"));
How can I achieve the same using LightInject?
EDIT: My example does not work, because the created logger cannot be cast to ILogger<T>. I have instead posted my workaround as a solution below.
Turns out I had to solve my problem in a different way:
I copied over XunitLogger from Microsoft.Extensions.Logging.Testing
I created a generic version:
public class XunitLogger<T> : XunitLogger, ILogger<T>
{
public XunitLogger(ITestOutputHelper output) : base(output, typeof(T).Name, LogLevel.Information)
{
}
}
I registered the test output helper and the logger:
public TestBase(ITestOutputHelper testOutputHelper)
{
Container.RegisterInstance(testOutputHelper);
Container.Register(typeof(ILogger<>), typeof(XunitLogger<>));
}
The key here was that ILogger<T> must be implemented by a generic class, e.g. XunitLogger<T>. Now the messages are logged to my test output.

Which types should I register with my IOC container for Umbraco ContentService to be instantiated?

One of the classes in my Umbraco project depends on IContentService. I'm trying to provide an IContentService to this class with an IOC container.
Here is how I'm registering IContentService with my IOC (Autofac)
builder.RegisterType<Umbraco.Core.Services.ContentService>().As<IContentService>();
However, Umbraco.Core.Services.ContentService requires these constructor parameters:
public ContentService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IPublishingStrategy publishingStrategy, IDataTypeService dataTypeService, IUserService userService);
Autofac gets stuck because it doesn't know about any of these types yet. Here's a stack trace:
Exception Details: Autofac.Core.DependencyResolutionException: None of the constructors found with
'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Umbraco.Core.Services.ContentService' can be
invoked with the available services and parameters:Cannot resolve parameter
'Umbraco.Core.Persistence.RepositoryFactory repositoryFactory' of constructor 'Void
.ctor(Umbraco.Core.Persistence.UnitOfWork.IDatabaseUnitOfWorkProvider, Umbraco.Core.Persistence.RepositoryFactory,
Umbraco.Core.Logging.ILogger, Umbraco.Core.Events.IEventMessagesFactory, Umbraco.Core.Publishing.IPublishingStrategy,
Umbraco.Core.Services.IDataTypeService, Umbraco.Core.Services.IUserService)'.
Which types should I register with Autofac so that my ContentService can be instantiated?
Here's how I solved this particular problem. Thanks to Claus for the help.
I need to use RegisterInstance() (docs here) instead of RegisterType<T>()
public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
var builder = new ContainerBuilder();
// Register the components we need resolving with Autofac
builder.RegisterInstance(applicationContext.Services.MemberService).As<IMemberService>();
builder.RegisterInstance(applicationContext.Services.ContentService).As<IContentService>();
// ... Configuration for dependency resolution here ...
}
The reason for this is that Umbraco creates an instance of ContentService and configures it correctly. Autofac needs to be told to use this instance instead of trying to create it's own.

Castle Windsor to Autofac

I have a DevExpress example mvc web site application. It use Castle Windsor as an IOC. I just tried to replace via Autofac but no luck!
here is the sample code:
container
.Register(Component
.For<DbRepositories.ClinicalStudyContext>()
.LifestylePerWebRequest()
.DependsOn(new { connectionString }))
.Register(Component
.For<DbRepositories.IClinicalStudyContextFactory>()
.AsFactory())
.Register(Component
.For<FirstStartInitializer>()
.LifestyleTransient())
.Register(Component
.For<IUserRepository>()
.ImplementedBy<DbRepositories.UserRepository>())
and this is my Autofac conversion:
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.Register(c =>
new DbRepositories.AdminContext(connectionString))
.InstancePerHttpRequest();
builder.RegisterType<DbRepositories.IAdminContextFactory>()
.As<DbRepositories.IAdminContextFactory>();
builder.RegisterType<DbRepositories.UserRepository>()
.As<IUserRepository>().InstancePerHttpRequest();
there is no implementetion for AsFactory() on Autofac regarding my research.
this is the IAdminContextFactory interface:
public interface IAdminContextFactory
{
AdminContext Retrieve();
}
and this is the error application says:
No constructors on type
'Admin.Infrastructure.EFRepository.IAdminContextFactory' can be found
with 'Public binding flags'.
can anyone help?
thanks.
Your IAdminContextFactory registration will fail, because the first part of the RegisterType must be a service type. In this case, a class that implements the IAdminContextFactory interface. Autofac tries to build an instance of the type, which certainly will fail because you cannot instantiate an interface.
So, what you need is an implementation of the IAdminContextFactory interface. The Castle AsFactory method generates this implementation for you. You can get this behavior with the Autofac AggregateService extra.
With the bits in place you can do:
builder.RegisterAggregateService<IAdminContextFactory>();

IValidator could not be located with the ServiceLocator

I get the following error when using sharparchitecture and try to call IValidatable.IsValid on a Domain Object.
How can I register an instance of the NHibernate validator against the common service locator?
I have seen the following unit tests:
http://code.google.com/p/sharp-architecture/source/browse/trunk/src/SharpArch/SharpArch.Tests/SharpArch.Core/SafeServiceLocatorTests.cs?spec=svn385&r=385
Any help with this would really be appreciated.
The needed dependency of type IValidator could not be located with the ServiceLocator. You'll need to register it with the Common Service Locator (CSL) via your IoC's CSL adapter.
at SharpArch.Core.SafeServiceLocator`1.GetService() in C:\MyStuff\Projects\SharpArchGitHub\src\SharpArch\SharpArch.Core\SafeServiceLocator.cs:line 29
at SharpArch.Core.DomainModel.ValidatableObject.IsValid() in C:\MyStuff\Projects\SharpArchGitHub\src\SharpArch\SharpArch.Core\DomainModel\ValidatableObject .cs:line 11
at Tuhdoo.Common.Validation.ValidatableExtensions.Validate(IValidatable entity) in D:\Repository\Tuhdoo\src\Tuhdoo.Common\Validation\ValidatableExtensions.cs:line 26
This turned out to be pretty obvious I had a slap head moment when I realised I hadn't registered the IValidator with my DI Conatiner.

StructureMap Error 202 Setting up IOC container

I'm getting an error:
StructureMap Exception Code: 202
No Default Instance defined for PluginFamily MVCPoco.Services.IService, MVCPoco.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Line 96: {
Line 97: Type controllerType = base.GetControllerType(context, controllerName);
Line 98: return ObjectFactory.GetInstance(controllerType) as IController;
Line 99: }
Line 100: }
the error occurs in line 98
Any ideas?
I'm using asp.net mvc 2 preview 2 that ships with visual studio 2010.
The controller you are trying to instantiate has a constructor dependency on IService. You have to make sure that you register a concrete implementation of IService when you configure StructureMap.
The DefaultConventionScanner will only register implementations that have the same name as their interface (without the leading I). So, unless your implementation of IService is named Service, it will not be registered automatically. To register it explicitly, add something like this to your inititalization script:
x.For<IService>().Use<MyService>();
Alternatively, if you are running StructureMap from the latest source code, you can make use of the SingleImplementationScanner in your Scan() expression:
y.With(new SingleImplementationScanner());
and that will automatically register concrete types if they are the only implementation of an interface in the scanned code, regardless of name.
You must register the types to be injected at application start within the ObjectFactory.Configure function. Check out the documents over on Structure Map's site for Configuring your IOC Container.
Andrew
Well, i've set up correctly the structuremap i've just switched to the method
public static void Configure()
{
ObjectFactory.Initialize(x =>
x.AddRegistry(new IOCRegistry())); // in here i have registered my dependencies with for method.
}

Categories