ServicesProvider / Dependency Injection in C# Unit test classes - c#

I have serveal Unit Tests projects UT_A, UT_B, UT_C which all include a common UT_Common project containing common stuff for A, B, C.
I want A, B, C to have their own ServiceProvider to handle their DI, their own IConfiguration (Appsettings) etc...
I have coded in A, B, C project a class that builds their own dedicated
public static class ServicesBuilder_A
{
public static IHost ServicesHost { get; }
static ServicesBuilder()
{
IConfigurationRoot configurationRoot = null;
IHostBuilder host = Host.CreateDefaultBuilder().......
.....
ServicesHost = host.Build();
}
}
So the IHost is singleton, initialized at first use.
Now, when I start my unit tests of UT_A project, at some point I will need project UT_Common to access to the AppSettings UT_A appsettings and do stuff based on this specific file.
And of course, when I start UT_B, I need UT_Common to use UT_B IHost.
Since TU_COmmon is included in TU_A, UT_B, it does not know the static classes used in UT_A and UT_B and can't use them directly.
I firstly thought of setting a static class in UT_Common that would expose an IHost that I would set in UT_A, UT_B, when setting their IHost.
Adding at the end of previous building method:
public static class ServicesBuilderContainer
{
public static IHost ServicesHost { get; set; }
}
Into the IHost conf of UT_A, UT_B:
ServicesBuilderContainer.ServicesHost = ServicesHost;
But it does not really work, as UT_A.ServicesBuilder_A static ctor will only run when I try to get its IHost.
If I need to access UT_Common.ServicesBuilderContainer.ServicesHost first, then UT_A.ServicesBuilder_A.ServicesHost will not have been initialized yet so UT_Common.ServicesBuilderContainer.ServicesHost will be empty.
I am sure I am doing things wrong but I do not know how to fix this mess in a good way.
Thx for your advices :)
EDIT:
Well I am used to using DI in .NETCore controllers / Service classes :
public class MyController : ControllerBase
{
public MyController(IMyInterface myInterface)
{
...
}
}
But I did not find a way to have something similar in my own classes.
I suppose that in the case of Controllers, there is some .NetCore magic behind the scene that does not apply to my own classes?

Related

How to resolve dependencies for dynamic controller in .net core?

I am creating the controller dynamically for the types to be loaded from the dll. For that I created one base controller to handle dynamic controller request.
My dynamic controller has following dependencies in the construcor
public class Order
{
private readonly IDBLogger _logger;
private readonly IExceptionHandler _handler
public Order(IDBLogger logger, IExceptionHandler handler)
{
_logger=logger;
_handler=handler
}
public void GetOrderDetail()
{
_logger.log("....."); //Here I am getting null reference as I am not able resolve this _logger type.
/// rest code
}
}
Since the class is loaded from the dll how can I resolve this.
I think my assumption of your objective was way off and it actually seems to me you don't need to mess with ApplicationParts or FeatureProviders at all. To me it appears to be a DI registration issue.
I started with boilerplate .net core 3.1 MVC application (nothing fancy there)
then I added two more class library projects: Common and Orders
Common.dll
I assumed that your interfaces (I'll just use IDBLogger for brevity) must be made available to the controller assembly as well as to the main application. So both projects are set to depend on it.
namespace Common
{
public interface IDBLogger
{
void Log(string s);
}
}
Orders.dll
this assembly defines a web api controller:
using Common;
namespace Orders
{
public class Order
{
private readonly IDBLogger _logger;
public Order(IDBLogger logger)
{
_logger = logger;
}
public void GetOrderDetail()
{
_logger.Log("Inside GetOrderDetail");
}
}
}
MVC
as most of the code is stock standard I'd only list files that I changed.
Note, that now I'm relying on default Controller resolver I only need to register my types onto ServiceCollection
Startup.cs
...
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(); // add all controllers as you normally would. I think you don't need to mess with ApplicationParts. but if you do, you are already aware that https://stackoverflow.com/questions/36680933/discovering-generic-controllers-in-asp-net-core is a good example
services.AddScoped<IDBLogger, IdbLogger>();
// load assembly and register with DI
var assembly = Assembly.LoadFrom(Path.Combine("..\\path\\to", "Orders.dll"));
var orderType = assembly.ExportedTypes.First(t => t.Name == "Order");
services.AddScoped(orderType); // this is where we would make our type known to the DI container
var loadedTypesCache = new LoadedTypesCache(); // this step is optional - I chose to leverage the same DI mechanism to avoid having to load assembly in my controller for type definition. you can probably find a better approach at doing this
loadedTypesCache.LoadedTypes.Add("order", orderType);
services.AddSingleton(loadedTypesCache); // singleton seems like a good fit here
}
IdbLogger.cs
using Common;
using System;
namespace Test
{
public class IdbLogger : IDBLogger
{
public void Log(string s)
{
Console.WriteLine(s); // nothing fancy here either
}
}
}
ValuesController.cs
[Route("api/[controller]")]
[ApiController]
public class ValuesController
{
public ValuesController(IServiceProvider serviceProvider, LoadedTypesCache cache)
{
var order = serviceProvider.GetService(cache.LoadedTypes["order"]); // you could load the same assembly here to get the type again, but i opted to inject a dictionary with preloaded type instead
// following two lines are just to call the method. you probably have better way of doing it
var m = cache.LoadedTypes["order"].GetMethod("GetOrderDetail", BindingFlags.Public|BindingFlags.Instance);
m.Invoke(order, new object[] { });
}
[HttpGet]
public IEnumerable<string> Get()
{
return new [] { "value1", "value2" };
}
}
relying on built-in DI container allows us to not think about manually instantiating your dynamically loaded types (and their dependencies as long as they are known to the DI container). You might find that having to use reflection to work with these instances is a bit cumbersome so you might want to explore your options there.
hopefully this is the missing piece
You can dynamically load the dependencies and the controller using reflection.
For more info, you can visit the following link.
Assemblies

How do you inject in dotnet core project in static method an IConfiguration object?

I have a Redis store similar to this one. My problem is, since I am using .Net Core, on line 15, I should use configuration object that I normally inject in the constructor.
However, one cannot inject the configuration object in the static constructor, as static constructor should be parameterless in C#.
I tried adding a static method to initialise the config object, but then the constructor throws NullReferenceException because obviously the ctor is still called first, before the Init method, and it needs the config object... so what to do?
Doesn't seem like a good workaround.
Instead of doing all that work with statics and trying to get it to work (hint: it'd never work with a static constructor), I'd suggest you to move to newer patterns and use DI correctly.
If you don't really need the lazyness, this is as simple as injecting IConnectionMultiplexer:
services.AddScoped<IConnectionMultiplexer>(s => ConnectionMultiplexer.Connect(configuration["someSettings"]));
If you do need the lazyness:
// public interface IRedisStore { IConnectionMultiplexer RedisConnection { get; } }
public class RedisStore : IRedisStore
{
private readonly Lazy<ConnectionMultiplexer> LazyConnection;
public RedisStore(IConfiguration configuration)
{
var configurationOptions = new ConfigurationOptions
{
EndPoints = { configuration["someSettings"] }
};
LazyConnection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(configurationOptions));
}
public IConnectionMultiplexer RedisConnection => LazyConnection.Value;
}
and you'd inject it with:
services.AddScoped<IRedisStore, RedisStore>());

Bootstrapping an ASP.NET Core 2.1 application containing multiple module types using DI

Started building the infrastructure for a multi-tenant ASP.NET Core 2.1 application which is and will be composed of many modules.
The idea is to enable any modules which are to be added in the future, to be just plugged into the system, registering their own required dependencies on app startup and using the already registered dependencies (dependencies registered by other modules) if needed.
Let's first take a look at the sample code of how I imagined this would look like - from the top of my head.
Let's say we've got some kind of a module manager which we're gonna name just that - ModuleManager.
public class ModuleManager
{
// Let's store all of our module types here
private List<Type> moduleTypes;
void RegisterModules(Type webHostModuleType, IServiceCollection services)
{
// Find all module dependencies recursively
// (i.e. all modules that are specified in some, let's say 'DependsOn' attribute
// which decorates webHostModuleType)
moduleTypes = FindDependencies();
// Now we need to register all dependencies
foreach (Type moduleType in moduleTypes)
{
services.AddSingleton(moduleType);
}
// ... and we shouldn't forget to register the webHostModuleType too
services.AddSingleton(webHostModuleType);
}
}
Let's stop there for now and first define the module type. I think it is expected to presume that each module type can have different properties and fields based on their needs, but we will have to make all of them derive from a base module type. Let's call it BaseModule and this is how I imagined it to be:
public abstract class BaseModule
{
// I've currently got no idea on how this method should be defined
// Because it's supposed to register the concrete module's dependencies
// after the module has been instantiated... is that even possible?
// Should it be some kind of a factory method rather than void
// and serve as a lazy initializer? Is that also even possible?
// Something that should make use of IOptions<>?
public virtual void Init()
{
}
// Maybe some post-init code will be needed too
public virtual void PostInit()
{
}
}
And then we will have some concrete module types defined like this:
public class CoreModule : BaseModule
{
// some dependencies that need to be injected...
private readonly IHostingEnvironment hostingEnvironment;
private readonly IDontKnowSomeOtherDependency someOtherDependency;
public CoreModule(IHostingEnvironment hostingEnvironment, IDontKnowSomeOtherDependency someOtherDependency)
{
this.hostingEnvironment = hostingEnvironment;
this.someOtherDependency = someOtherDependency;
}
public override void Init()
{
// Somehow register additional services defined by this module,
// after it's been instantiated
}
}
And let's say, for the completeness sake, our webHostModuleType is defined like this:
[DependsOn(typeof(CoreModule))]
public class WebHostModule : BaseModule
{
private readonly ISomeDependencyRegisteredInCoreModule someDependency;
public WebHostModule(ISomeDependencyRegisteredInCoreModule someDependency)
{
this.someDependency = someDependency;
}
public override void Init()
{
// Register some other service based on something from 'someDependency' field
}
}
And finally, let's go back to the module manager. Now it should have another method, executed after RegisterModules, which should instantiate each module in the correct order and then call Init() and PostInit() in the correct order, starting with the CoreModule and ending with WebHostModule. Something akin to this:
public void(?) LoadModules()
{
// Sort our modules first so dependencies come in first and webHostModuleType the last
SortEm(moduleTypes);
// Now we need to instantiate them.
// Can't do it manually as all of them might have different constructors
// So need to do it using our service collection
IServiceProvider serviceProvider = serviceCollection.BuildServicePRovider();
foreach (Type moduleType in moduleTypes)
{
BaseModule moduleInstance = serviceProvider.GetRequiredService(moduleType) as BaseModule;
// This is where we can register everything needed by the module instance.
// But can we?
moduleInstance.Init();
moduleInstance.PostInit();
}
// Maybe return the IServiceProvider instance we've built
// so we can return in to the `ConfigureServices` and return to ASP.NET Core from there?
}
As you can see, this approach raises many questions. Am I going in the right direction at all? Is there a way to register services from withing modules' Init() and PostInit() methods correctly?
If I call BuildServiceProvider() and then instantiate singleton instances, I would have to return that IServiceProvider instance back to ConfigureServices() so ASP.NET Core can use it. If I don't, it will build a new one and then all these singletons will be instantiated again.
But if I call ConfigureServices() then I won't be able to add new services, which I have to do after modules have been instantiated. What is the approach, if it's possible at all? Any opinions, ideas?
Wow such wall of text, thanks for reading at all!
Well, just one more opinion, but we are using the same standard ad the Net Core team, creating extension methods, so we just need to add the services were they are required:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddVtaeCommonServices();
services.AddMyServiceMX(Configuration);
services.AddOtherService(Configuration);
return VtaeConfig.ConfigVtae(services);
}
}
With this extension methods for example:
public static class CommonServicesExtension
{
public static IServiceCollection AddVtaeCommonServices(this IServiceCollection services)
{
services.AddNodaDateTime();
services.AddMemoryCache();
services.AddScoped<AuthorizedIpFilter>();
services.AddScoped<HttpContextManager>();
services.AddTransient<ProspectService>();
services.AddTransient<TokenService>();
services.AddTransient<TokenGenerator>();
services.AddTransient<ProspectsRepository>();
services.AddSingleton<UniqueIDGenerator>();
services.AddSingleton<SchedulerService>();
services.AddSingleton<ChecksumService>();
return services;
}
}
This way we can extract our functions to nuget packages and then simply re utilize them by adding the AddXXXService() in our startup

Mock implementation for use in automatic UI testing

I am working on adding basic automatic UI tests to the block of unit tests we run with each nightly build. We used MSTest coded UI and created a script.
The code-behind is dependent upon IClientManager which both the real manager and mock implement.
My problem is that I don't know how to switch automatically between the real and mock implementations inside the button click handler, when running a test.
My two other constraints are that I can't have a dependency on the mock assembly in the code-behind and that I can't use a DI framework, since the client is "security conscious" and getting a framework approved might take months.
Is there any way of doing this manually, and hopefully, not a bigger problem than the problem I am looking to solve?
Thank you!
You could build your own simple object container if you can't use a third party one (which is silly but I understand, I've been there before)
here is something that I whipped up that could get you started... haven't tested it and it is really rough, but hopefully you get the idea
public static class ObjectFactory
{
static IDictionary<Type, object> _factory = new Dictionary<Type, object>();
public static void Register<T>(Func<T> builder)
{
if (_factory.ContainsKey(typeof(T)))
_factory[typeof(T)] = builder;
else
_factory.Add(typeof(T), builder);
}
public static T GetInstance<T>()
{
if (_factory.ContainsKey(typeof(T)))
throw new ArgumentException(string.Format("Type <{0}> not registered in ObjectFactory", typeof(T).Name));
return ((Func<T>)_factory[typeof(T)])();
}
}
public interface IClientManager { }
public class RealClientManager : IClientManager { }
public class MockClientManager : IClientManager { }
public class MyView
{
public MyView()
{
// probably better to do this registry in some sort of application initialization
ObjectFactory.Register<IClientManager>(() => new RealClientManager());
}
public void SomeMethodThatNeedsClientManager()
{
var clientManager = ObjectFactory.GetInstance<IClientManager>();
}
}
public class MyTester
{
[TestMethod()]
public void SomeTest()
{
var view = new MyView();
// swap the client manager in the test
ObjectFactory.Register<IClientManager>(() => new MockClientManager());
// Asserts
}
}
you can see that if you've used StructureMap or some other DI container before they do a lot of the same thing with a lot of added niceties such as traversing your object graph and registering objects automatically based on conventions, managing object lifecycles, scoping of containers, etc... a lot of this stuff you could implement yourself too... but you should just really used a tried and true solution such as StructureMap

Ways of keeping configuration code out of logic code using Dependency Injection

How can keep all the configuration file code out of my logic code using Settings (ApplicationSettingsBase) and Dependency Injection?
With configuration I mean a customer specific configuration file.
Do I really have to inject a configuration class everytime I need it or is there another pattern?
It would be great to get some sample code!
Samples:
Static Configuration:
public static class StaticConfiguration
{
public static bool ShouldApplySpecialLogic { get; set; }
public static string SupportedFileMask { get; set; }
}
public class ConsumerOfStaticConfiguration
{
public void Process()
{
if (StaticConfiguration.ShouldApplySpecialLogic)
{
var strings = StaticConfiguration.SupportedFileMask.Split(',');
foreach (var #string in strings)
{
}
}
}
}
Non static Configuration:
public interface IConfiguration
{
bool ShouldApplySpecialLogic { get; set; }
string SupportedFileMask { get; set; }
}
public class Configuration : IConfiguration
{
public bool ShouldApplySpecialLogic { get; set; }
public string SupportedFileMask { get; set; }
}
public class Consumer
{
private readonly IConfiguration _configuration;
public Consumer(IConfiguration configuration)
{
_configuration = configuration;
}
public void Process()
{
if (_configuration.ShouldApplySpecialLogic)
{
var strings = _configuration.SupportedFileMask.Split(',');
foreach (var #string in strings)
{
}
}
}
}
Static Context with non static configuration:
public static class Context
{
public static IConfiguration Configuration { get; set; }
}
public class ConsumerOfStaticContext
{
public void Process()
{
if (Context.Configuration.ShouldApplySpecialLogic)
{
var strings = Context.Configuration.SupportedFileMask.Split(',');
foreach (var #string in strings)
{
}
}
}
}
Configuration classes reduce cohension and increase coupling in the consumers. This is because there may be many settings that don't relate to the one or two needed by your class, yet in order to fulfill the dependency, your implementation of IConfiguration must supply values for all of the accessors, even the irrelevant ones.
It also couples your class to infrastructure knowledge: details like "these values are configured together" bleed out of the application configuration and into your classes, increasing the surface area affected by changes to unrelated systems.
The least complex, most flexible way to share configuration values is to use constructor injection of the values themselves, externalizing infrastructure concerns. However, in a comment on another answer, you indicate that you are scared of having a lot of constructor parameters, which is a valid concern.
The key point to recognize is that there is no difference between primitive and complex dependencies. Whether you depend on an integer or an interface, they are both things you don't know and must be told. From this perspective, IConfiguration makes as much sense as IDependencies. Large constructors indicate a class has too much responsibility regardless of whether the parameters are primitive or complex.
Consider treating int, string and bool like you would any other dependency. It will make your classes cleaner, more focused, more resistant to change, and easier to unit test.
The important part to realize is that configuration is only one among several sources of values that drive your application's behavior.
The second option (non-static configuration) is best because it enables you to completely decouple the consumer from the source of the configuration values. However, the interface isn't required, as configuration settings are normally best modeled as Value Objects.
If you still want to read the values from a configuration file, you can do that from the application's Composition Root. With StructureMap, it might looks something like this:
var config = (MyConfigurationSection)ConfigurationManager.GetSection("myConfig");
container.Configure(r => r
.For<Consumer>()
.Ctor<MyConfigurationSection>()
.Is(config));
One way is to inject a configuration interface like you post. Here are a couple other ways.
Exposing a Setter
class Consumer
{
public bool ShouldApplySpecialLogic { get; set; }
...
}
In the composition root, you can read a config file or hardcode it. Autofac example:
builder.RegisterType<Consumer>().AsSelf()
.OnActivated(e => e.Instance.ShouldApplySpecialLogic = true);
This is probably only advisable when you have a good default
Constructor Injection
public class Server
{
public Server(int portToListenOn) { ... }
}
In the composition root:
builder.Register(c => new Server(12345)).AsSelf();
In my applications I do what you have done above with IoC. That is to say, having my IoC container (StructureMap also) inject an IApplicationSettings into my classes.
For example, in an ASP.NET MVC3 project it may look like:
Public Class MyController
Inherits Controller
...
Private ReadOnly mApplicationSettings As IApplicationSettings
Public Sub New(..., applicationSettings As IApplicationSettings)
...
Me.mApplicationSettings = applicationSettings
End Sub
Public Function SomeAction(custId As Guid) As ActionResult
...
' Look up setting for custId
' If not found fall back on default like
viewModel.SomeProperty = Me.mApplicationSettings.SomeDefaultValue
Return View("...", viewModel)
End Function
End Class
My implementation of IApplicationSettings pulls most things from the app's .config file and has a few hard-coded values in there as well.
My example wasn't logic flow-control (like your example), but it would have worked just the same if it was.
The other way to do this would be to do a service-locator type pattern, where you ask your Dependency Injection container to get you an instance of the configuration class on-the-fly. Service-Location is considered an anti-pattern generally, but might still be of use to you.

Categories