I'm trying to write an xunit test for a class (in a .net Core project) that looks something like:
public Class FoodStore:IFoodStore
{
FoodList foodItems;
public FoodStore(IOptions<FoodList> foodItems)
{
this.foodItems = foodItems;
}
public bool IsFoodItemPresentInList(string foodItemId)
{
//Logic to search from Food List
}
}`
Note: FoodList is actually a json file, containing data, that is loaded and configured in the Startup class.
How can I write an xunit test with appropriate dependency injection to test the IsFoodItemPresentInList method ?
You can create an instance of IOptions<FoodList> using the Options.Create method:
var foodListOptions = Options.Create(new FoodList());
You could use OptionsWrapper<T> class to fake your configuration. Then you can pass in this object to your class that you want to test. That way you don't have to use DI or read the real configuration.
Something like this:
var myConfiguration = new OptionsWrapper<MyConfiguration>(new MyConfiguration
{
SomeConfig = "SomeValue"
});
var yourClass = new YourClass(myConfiguration);
I have encountered a similar problem (using xUnit), after some struggle, I worked it out.
The answer is so late, but should be helpful for others.
For your Question:
public Class FoodStoreTest
{
private readonly IConfigurationRoot _configuration;
private readonly IServiceProvider _serviceProvider;
public FoodStoreTest(){
// read Json
var configBuilder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
_configuration = configBuilder.Build();
// SetUp DI
var services = new ServiceCollection();
services.AddOptions(); // this statement is required if you wanna use IOption Pattern.
services.Configure<YuntongxunOptions>(_configuration.GetSection("yuntongxun"));
_serviceProvider = services.BuildServiceProvider();
}
[Fact]
public void GetFootItemOption()
{
IOption<FoodList> optionAccessor = _serviceProvider.GetService<IOptions<FoodList>>();
FoodList footListOptions = optionAccessor.value;
Assert.NotNull(footListOptions)
// ...
}
}
Also, you should copy "appSettings.json" to your project root folder.
In a unit test, you typically don't use Dependency Injection, since it's you who controls the creation of the tested object.
To supply a suitable object that implements IOptions<FoodList> you can implement a fake class with the desired behavior yourself, or use some mocking framework to configure the instance on the fly, for example Moq.
As suggested by the other answers, in your test class you can create an options instance just for testing.
You can do it like this;
public class FakeFoodList : IOptions<FoodList>
{
public FoodList Value
{
get
{
return new FoodList(); // TODO: Add your settings for test here.
}
}
}
And then call it like this;
var foodOptions = new FakeFoodList();
var foodStore = new FoodStore(foodOptions);
var response = foodStore.Act();
Assert.Equal("whatever", response);
Related
I've done interception using Castle.DynamicProxy and StructureMap 2.6 API but now can't do it using StructureMap 3.0. Could anyone help me find updated documentation or even demo? Everything that I've found seems to be about old versions. e.g. StructureMap.Interceptors.TypeInterceptor interface etc.
HAHAA! I f***in did it! Here's how:
public class ServiceSingletonConvention : DefaultConventionScanner
{
public override void Process(Type type, Registry registry)
{
base.Process(type, registry);
if (type.IsInterface || !type.Name.ToLower().EndsWith("service")) return;
var pluginType = FindPluginType(type);
var delegateType = typeof(Func<,>).MakeGenericType(pluginType, pluginType);
// Create FuncInterceptor class with generic argument +
var d1 = typeof(FuncInterceptor<>);
Type[] typeArgs = { pluginType };
var interceptorType = d1.MakeGenericType(typeArgs);
// -
// Create lambda expression for passing it to the FuncInterceptor constructor +
var arg = Expression.Parameter(pluginType, "x");
var method = GetType().GetMethod("GetProxy").MakeGenericMethod(pluginType);
// Crate method calling expression
var methodCall = Expression.Call(method, arg);
// Create the lambda expression
var lambda = Expression.Lambda(delegateType, methodCall, arg);
// -
// Create instance of the FuncInterceptor
var interceptor = Activator.CreateInstance(interceptorType, lambda, "");
registry.For(pluginType).Singleton().Use(type).InterceptWith(interceptor as IInterceptor);
}
public static T GetProxy<T>(object service)
{
var proxyGeneration = new ProxyGenerator();
var result = proxyGeneration.CreateInterfaceProxyWithTarget(
typeof(T),
service,
(Castle.DynamicProxy.IInterceptor)(new MyInterceptor())
);
return (T)result;
}
}
The problem here was that SM 3.* allows interception for known types, i.e. doing something like this:
expression.For<IService>().Use<Service>().InterceptWith(new FuncInterceptor<IService>(service => GetProxyFrom(service)));
But what if you'd like to include the interception logic inside your custom scanning convention where you want to intercept all instances of type with specific signature (types having name ending on 'service', in my case)?
That's what I've accomplished using Expression API and reflection.
Also, I'm using here Castle.DinamicProxy for creating proxy objects for my services.
Hope someone else will find this helpful :)
I find the best place to go for any new versions is directly to the source.
If it's written well, then it will include test cases. Thankfully structuremap does include test cases.
You can explore the tests here
In the meantime I've written an example of an Activator Interceptor, and how to configure it.
static void Main()
{
ObjectFactory.Configure(x =>
{
x.For<Form>().Use<Form1>()
.InterceptWith(new ActivatorInterceptor<Form1>(y => Form1Interceptor(y), "Test"));
});
Application.Run(ObjectFactory.GetInstance<Form>());
}
public static void Form1Interceptor(Form f)
{
//Sets the title of the form window to "Testing"
f.Text = "Testing";
}
EDIT:
How to use a "global" filter using PoliciesExpression
[STAThread]
static void Main()
{
ObjectFactory.Configure(x =>
{
x.Policies.Interceptors(new InterceptorPolicy<Form>(new FuncInterceptor<Form>(y => Intercept(y))));
});
Application.Run(ObjectFactory.GetInstance<Form>());
}
private static Form Intercept(Form form)
{
//Do the interception here
form.Text = "Testing";
return form;
}
Structuremap experts,
I found this post on stackoverflow ...
Passing constructor arguments when using StructureMap
Someone suggested to use the StructureMap configuration with runtime value like this
For<IProductProvider>().Use<ProductProvider>.Ctor<string>("connectionString").Is(someValueAtRunTime);
But example is not adequate enough to understand its declaration and usage. I try to find on StructureMap site as well but not much help ...
In my situation, I want to pass on the dependency of concrete DbContext (IDbContext) to the constructor of the class with connection string dynamically created during run time within that class.
Finally I managed to make it working ...
Here how I did it ...
Hope it will help someone, and thanks to PHeiberg for answer me before and showing me right direction.
Interface Definition
public interface ICreditCard
{
string GetName();
}
public interface IAdditionalCreditCard : ICreditCard
{
}
public class AdditionalCreditCard : IAdditionalCreditCard
{
private readonly string _name;
public AdditionalCreditCard(string name)
{
_name = name;
}
public string GetName()
{
return _name;
}
}
Define function in Structure map config code
Func<string, IAdditionalCreditCard> additionalCreditCard = value =>
ObjectFactory.With("name").EqualTo(value).GetInstance<AdditionalCreditCard>();
Add following configuration in ObjectFactory.Configure
ObjectFactory.Configure(config =>
{
config.For<Func<string, IAdditionalCreditCard>>().Use(additionalCreditCard);
});
And in code ...
public class PaymentSystem
{
private readonly Func<string, IAdditionalCreditCard> _addtionalCreditCard;
private IAdditionalCreditCard _addCreditCard;
public PaymentSystem(Func<string, IAdditionalCreditCard> additionalCredit)
{
_addtionalCreditCard = additionalCredit;
}
public string AddtionalSystemType()
{
_addCreditCard = _addtionalCreditCard("American Express");
return _addCreditCard.GetName();
}
}
The code you are posting is supposed to go in the setup code for StructureMap, which can go in the Initialize/Configure method or a Registry. The setup code is normally executed only once in the application's life cycle. So if you know the connection string value when the application is stared and you configure StructureMap, you can put the code you posted in the initialization of StructureMap. If the value is not known until later on, you need some kind of factory approach.
A factory approach could be done like this (in your StructureMap configuration code):
Func<string, IDbContext> createContext = value => {
/* create context based on value */
};
ObjectFactory.Initialize(c => {
For<Func<string, IDbContext>>().Use(createContext);
// The rest of you configuration ...
});
You can now use the Func to create an instance of the context when you need it:
public class ProductProvider : IProductProvider
{
private readonly Func<string, IDbContext> _contextCreator;
public ProductProvider(Func<string, IDbContext> contextCreator)
{
_contextCreator = contextCreator;
}
public IEnumerable<Product> GetProducts(string someValue)
{
using(var context = contextCreator(someValue))
{
return SomeOperationOnThe(context);
}
}
}
We inject IQueryHandler<TQUery,TResult> into our MVC controllers. We globally register all of these in the container
We have written a decorator that can cache the results of IQueryHandler.
We want to sometimes get cached reults and other times not from the same handler.
Is it possible to conditionally get a decorated handler based on the name of the constructor parameter. e.g. inject IQueryHandler<UnemployedQuery, IEnumerable<People>> cachedPeopleHandler if we prefix constructor parameter name with cached we actually get it wrapped with decorator?
Just trying to use a more convention over configuration approach to simplify things.
Yes it's possible to do it. Below is a simple working example on how you can achieve it:
class Program
{
public interface IQueryHandler{}
private class QueryHandler : IQueryHandler
{
}
private class CacheQueryHandler : IQueryHandler
{
}
public interface IService
{
}
private class Service : IService
{
private readonly IQueryHandler _queryHandler;
private readonly IQueryHandler _cacheQueryHandler;
public Service(IQueryHandler queryHandler, IQueryHandler cacheQueryHandler)
{
_queryHandler = queryHandler;
_cacheQueryHandler = cacheQueryHandler;
}
public override string ToString()
{
return string.Format("_queryHandler is {0}; _cacheQueryHandler is {1}", _queryHandler,
_cacheQueryHandler);
}
}
static void Main(string[] args)
{
var builder = new ContainerBuilder();
// Register the dependency
builder.RegisterType<QueryHandler>().As<IQueryHandler>();
// Register the decorator of the dependency
builder.RegisterType<CacheQueryHandler>().Keyed<IQueryHandler>("cache");
// Register the service implementation
builder.RegisterType<Service>().AsSelf();
// Register the interface of the service
builder.Register(c =>
{
var ctor = typeof (Service).GetConstructors()[0];
var parameters =
ctor.GetParameters()
.Where(p => p.Name.StartsWith("cache"))
.Select(p => new NamedParameter(p.Name, c.ResolveKeyed("cache", p.ParameterType)));
return c.Resolve<Service>(parameters);
}).As<IService>();
using (var container = builder.Build())
{
var service = container.Resolve<IService>();
Console.WriteLine(service.ToString());
Console.ReadKey();
}
}
}
Update:
Basically you need to:
1. Think up a general convention. Prefix "cache" of ctor parameter name in your case.
2. Register your dependencies as usual.
3. Register your decorators, so they don't overwrite your original dependencies and you can easily resolve them basing on your convention. e.g. Keyed, Named, via Attribute, etc.
4. Register you actual implementation of class that uses decorators
5. Register your interface that describes the class via lambda expression that has all magic inside.
Note: I provided just a simple and working example. It's on you to make it nice, easy to use and fast e.g. make it as an extension, generic, cache reflection results etc. It's not difficult anyway.
Thanks.
Following on from this question I would like autofac to inject the type of the declaring object into the constructor of my NLog service, so that it can correctly log which type is logging entries.
My NLogService class looks like this...
public class NLogService : ILogService
{
private readonly Logger _logger;
public NLogService(Type t)
{
var consumerType = t.DeclaringType.FullName;
_logger = LogManager.GetLogger(consumerType);
}
However it fails on app startup because it obviously cannot work out what to inject into the constructor of the NLogService with the following error...
None of the constructors found with
'Public binding flags' on type
'MyProduct.Domain.Services.Logging.NLogService'
can be invoked with the available
services and parameters: Cannot
resolve parameter 'System.Type t' of
constructor 'Void .ctor(System.Type)'.
So, my question is - how do i instruct autofac to inject the type of the calling class?
I tried this...
public NLogService(Type t)
{
var method = MethodBase.GetCurrentMethod();
Type consumingType = method.DeclaringType;
var consumerType = consumingType.FullName;
var consumerType = t.DeclaringType.FullName;
_logger = LogManager.GetLogger(consumerType);
}
But i just end up with MyProduct.Domain.Services.Logging.NLogService
What i want is the type of the class that is doing the actual logging.
i have already tried this suggestion and it didnt work for me either.
Could make your NLogService generic, i.e. NLogService<T> and use Autofac's open generics support?
Then you could do this:
public class NLogService<T> : ILogger<T>
{
private readonly Logger _logger;
public NLogService()
{
_logger = LogManager.GetLogger(typeof(T).FullName);
}
}
There is no real good way to do this with Autofac, because does not have support for 'context based injection' (which is what you are trying to do). There is a workaround, but it aint pretty...
What you can do is revert to property injection and define a base class or interface for that ILogService property. For instance, you can define the following interface:
public interface ILoggerContainer
{
public ILogService Logger { get; set; }
}
Now you can implement this interface on all types that need a logger:
public class Consumer : IConsumer, ILoggerContainer
{
public ILogService Logger { get; set; }
}
With this in place you can configure Autofac as follows:
builder.RegisterType<ILoggerContainer>()
.OnActivating(e =>
{
var type = typeof(LogService<>)
.MakeGenericType(e.Instance.GetType());
e.Instance.Logger = e.Context.Resolve(type);
});
Another workaround, that you may find cleaner is to inject an ILogger<T> with the same type as the type of the parent type:
public class Consumer : IConsumer
{
public Consumer(ILogger<Consumer> logger) { }
}
This makes the configuration much easier and prevents you from having to have a base class. Which one is most appropriate is up to you.
As I said, these are workarounds, but to be honest, you might need to reconsider your logging strategy in your application. Perhaps you are logging at too many places. In the applications I write there is hardly ever a need to log, and when I do, I write an logging message that is expressive enough so that there is no need to communicate the type that triggered the event. And when you log exception, you will always have a complete stack trace (and exception logging should almost only happen in the outer layer of your application and not within services anyway).
The following technique works well in our experience:
Create an attribute like below, which can be applied at class level or at the injection site:
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class)]
public class LoggerAttribute : Attribute
{
public readonly string Name;
public LoggerAttribute(string name)
{
Name = name;
}
}
Create an Autofac module that you register with the ContainerBuilder:
public class LogInjectionModule : Module
{
protected override void AttachToComponentRegistration(IComponentRegistry registry, IComponentRegistration registration)
{
registration.Preparing += OnComponentPreparing;
}
static void OnComponentPreparing(object sender, PreparingEventArgs e)
{
var typePreparing = e.Component.Activator.LimitType;
// By default, the name supplied to the logging instance is the name of the type in which it is being injected into.
string loggerName = typePreparing.FullName;
//If there is a class-level logger attribute, then promote its supplied name value instead as the logger name to use.
var loggerAttribute = (LoggerAttribute)typePreparing.GetCustomAttributes(typeof(LoggerAttribute), true).FirstOrDefault();
if (loggerAttribute != null)
{
loggerName = loggerAttribute.Name;
}
e.Parameters = e.Parameters.Union(new Parameter[]
{
new ResolvedParameter(
(p, i) => p.ParameterType == typeof (Logger),
(p, i) =>
{
// If the parameter being injected has its own logger attribute, then promote its name value instead as the logger name to use.
loggerAttribute = (LoggerAttribute)
p.GetCustomAttributes(typeof(LoggerAttribute),true).FirstOrDefault();
if (loggerAttribute != null)
{
loggerName = loggerAttribute.Name;
}
// Return a new Logger instance for injection, parameterised with the most appropriate name which we have determined above.
return LogManager.GetLogger(loggerName);
}),
// Always make an unamed instance of Logger available for use in delegate-based registration e.g.: Register((c,p) => new Foo(p.TypedAs<Logger>())
new TypedParameter(typeof(Logger), LogManager.GetLogger(loggerName))
});
}
}
You can now inject a named Logger in any one of these ways depending on individual scenarios:
By default, the injected logger name will be given the full type name of the class it is injected into:
public class Foo
{
public Foo(Logger logger)
{
}
}
Use a constructor parameter [Logger] attribute to override the logger name:
public class Foo
{
public Foo([Logger("Meaningful Name")]Logger logger)
{
}
}
Use a class-level [Logger] attribute to set the same logger name override for all constructor overloads:
[Logger("Meaningful Name")]
public class Foo
{
public Foo(Logger logger, int something)
{
}
public Foo(Logger logger, int something, DateTime somethingElse)
{
}
}
Use constructor parameter [Logger] attributes on each constructor overload to set different logger names depending on the context of how you were constructed:
public class Foo
{
public Foo(Logger("Meaningful Name")]Logger logger, int something)
{
}
public Foo(Logger("Different Name")]Logger logger, int something, DateTime somethingElse)
{
}
}
IMPORTANT NOTE: If you register types to be resolved with logger constructor injection using Autofac's delegate registration, you MUST use the two parameter overload like so: Register((c,p) => new Foo(p.TypedAs<Logger>()).
Hope this helps!
It is possible to do this without generics.
However, please note that in Autofac 6.x, the resolution process has changed to use a resolve pipeline. This doesn't matter for most scenarios, but it does when you want to use the lifetime events like OnPreparing, etc. Most of the answers here on SO around overriding the Preparing event are very old and are now outdated. You can't override Preparing directly anymore.
There is an example on the Autofac documentation site doing this for log4net, and it works with NLog with only minor changes. Here is the basic idea:
public class Log4NetMiddleware : IResolveMiddleware
{
public PipelinePhase Phase => PipelinePhase.ParameterSelection;
public void Execute(ResolveRequestContext context, Action<ResolveRequestContext> next)
{
// Add our parameters.
context.ChangeParameters(context.Parameters.Union(
new[]
{
new ResolvedParameter(
(p, i) => p.ParameterType == typeof(ILog),
(p, i) => LogManager.GetLogger(p.Member.DeclaringType)
),
}));
// Continue the resolve.
next(context);
// Has an instance been activated?
if (context.NewInstanceActivated)
{
var instanceType = context.Instance.GetType();
// Get all the injectable properties to set.
// If you wanted to ensure the properties were only UNSET properties,
// here's where you'd do it.
var properties = instanceType
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.PropertyType == typeof(ILog) && p.CanWrite && p.GetIndexParameters().Length == 0);
// Set the properties located.
foreach (var propToSet in properties)
{
propToSet.SetValue(context.Instance, LogManager.GetLogger(instanceType), null);
}
}
}
}
Please also note that you have to understand how middleware works in Autofac. The documentation is a good place to start.
I am trying to configure the NCommon NHRepository in my project with Structure Map. How do I stop it from choosing the greediest constructor?
public class NHRepository<TEntity> : RepositoryBase<TEntity>
{
public NHRepository () {}
public NHRepository(ISession session)
{
_privateSession = session;
}
...
}
My structure map configuration
ForRequestedType(typeof (IRepository<>))
.TheDefaultIsConcreteType(typeof(NHRepository<>))
Cheers
Jake
You can set the [DefaultConstructor] Attribute for the constructor you wish as a default. In your case, setting it on the NHRepository() constructor would make it the default constuctor for StructureMap to initialize.
Update: well, in the latest version of StructureMap, using .NET 3.5 you can also specify it using the SelectConstructor method:
var container = new Container(x =>
{
x.SelectConstructor<NHRepository>(()=>new NHRepository());
});
Finally, I'm sure you would be able to define it in the XML configuration of StructureMap, but I haven't used that. You could do a little search on it. For more information on the above method, see: http://structuremap.sourceforge.net/ConstructorAndSetterInjection.htm#section3
So +1 for Razzie because this would work if the NHRepository was in my own assembly, instead I choose to wrap the NHRepository with my own Repository like below..
public class Repository<T> : NHRepository<T>
{
[DefaultConstructor]
public Repository()
{
}
public Repository(ISession session)
{
}
}
ForRequestedType(typeof (IRepository<>))
.TheDefaultIsConcreteType(typeof (Repository<>));