I've just switched to using the NInject.MockingKernel extension for my tests (NSubstitute).
However, it makes very hard to run my Web API integration tests because it will return mocks for all Web API interfaces also.
Can I automatically limit its application only to namespaces of my own?
I don't see how that is possible out of the box. Although it's not very hard to create such a kernel on your own.
This sample is of course very minimalistic though, but it should show you how it could be done. Or maybe there is someone with more knowledge of the Ninject internals.
public class NamespaceFilteringMockMissingBindingsResolver : MockMissingBindingResolver
{
public NamespaceFilteringMockMissingBindingsResolver(IMockProviderCallbackProvider mockProviderCallbackProvider)
: base(mockProviderCallbackProvider)
{
}
protected override bool TypeIsInterfaceOrAbstract(Type service)
{
return base.TypeIsInterfaceOrAbstract(service) && service.Namespace != null && service.Namespace.StartsWith("YourNamespace");
}
}
public class CustomNSubstituteMockingKernel : NSubstituteMockingKernel
{
public CustomNSubstituteMockingKernel()
{
this.AddComponents();
}
public CustomNSubstituteMockingKernel(INinjectSettings settings, params INinjectModule[] modules)
: base(settings, modules)
{
this.AddComponents();
}
private new void AddComponents()
{
this.Components.RemoveAll<IMissingBindingResolver>();
this.Components.Add<IMissingBindingResolver, SingletonSelfBindingResolver>();
this.Components.Add<IMissingBindingResolver, NamespaceFilteringMockMissingBindingsResolver>();
}
}
Update
You are right, you don't need to create your own kernel. You can also do it like this.
var kernel = new NSubstituteMockingKernel();
kernel.Components.RemoveAll<IMissingBindingResolver>();
kernel.Components.Add<IMissingBindingResolver, SingletonSelfBindingResolver>();
kernel.Components.Add<IMissingBindingResolver, NamespaceFilteringMockMissingBindingsResolver>();
Creating your own kernel might just be more handy than always writing those extra lines. Or you create some kind of factory method.
Related
I'm just taking my first baby steps in the MEF territory and wanted to do so using .net core 2.1.
Using VS 2017 (version 15.8.8) I've done a small Console App (.NET Core) with an interface
interface IMessageSender
{
void Send(string message);
}
and an implementation (in the same project)
[Export(typeof(IMessageSender))]
public class EmailSender : IMessageSender
{
public void Send(string message)
{
Console.WriteLine("EmailSender : " + message);
}
}
Finally I have a small compose method executed from my Main(string[] args)
[Import]
private void Compose()
{
var assembly_A = new[] { typeof(Program).GetTypeInfo().Assembly };
var config_A = new ContainerConfiguration().WithAssembly(assembly_A[0]);
var container_A = config_A.CreateContainer();
var msg_A = container_A.GetExport<IMessageSender>();
msg_A.Send("Hello");
}
It works as expected
However, if I add a new class library to my solution and move my implementation of Send(string) to the newly added project things do not work out.
namespace AnotherMefExtensionProjectNamespace
{
[Export(typeof(IMessageSender))]
public class EmailSenderExtended : IMessageSender
{
public void Send(string message)
{
Console.WriteLine("EmailSenderExtended : " + message);
}
}
}
The new Compose method
[Import]
public IMessageSender MessageSender { get; set; }
private void Compose()
{
var assembly_B = new[] { typeof(EmailSenderExtended).GetTypeInfo().Assembly };
var config_B = new ContainerConfiguration().WithAssembly(assembly_B[0]);
var container_B = config_B.CreateContainer();
var msg_B = container_B.GetExport<IMessageSender>();
msg_B.Send("Hello");
}
I've tried to compare the different configs and containers (_A versus _B in the examples) but can't understand what is different. I've even tried to extend the class ContainerConfiguration to load from a specified assembly and it works as long as the given file contains the Main method but fails if I use my "extended" .NET Core Class Library.
public static ContainerConfiguration WithChosenAssembly(this ContainerConfiguration configuration, string pathAndFile)
{
var context = AssemblyLoadContext.Default.LoadFromAssemblyPath(pathAndFile);
var ass_list = new List<Assembly>() { context };
configuration = configuration.WithAssemblies(ass_list, null);
return configuration;
}
I was under the impression that you extend your main application by developing a class library that basically implements the interfaces specified.
I seem to be unable to do this currently, but obviously I misunderstood something very basic.
If someone would care to put me on the right track or give me an alternative idea for "plug-in" development for .net core I would be very grateful.
King regards
Magnus
I realized that my test setup does not mimic any real world scenario and thus I brought my problems on myself.
Obviously I should have had three projects.
One project with only the interface definitions.
One "main" project where all my regular code exists.
One (or more) projects where my MEF implementations of the interfaces exist.
Reviewing my example and adhering to the obvious "design" above it all works exactly as it should.
Most StackOverflow users probably wouldn't make my blunder but for those that did, I hope the above helps. :-)
I've been using Dependency Injection in ASP.NET MVC the way I've explained in the below code, but I'm not sure if that is the right and standard way to do it. So I just wanna know if what I'm doing is wrong or if there is a better and more professional way to do it.
public interface IService {
public Boolean AddRecord(Object _Model);
}
public class Employee: IService {
DataBase Context = new DataBase();
public Boolean AddRecord(Object _Model) {
Context.Add((EmployeeModel) _Model);
return Context.SaveChanges() != 0;
}
}
public class DataController: Controller {
IService service;
public DataController(IService service) {
this.service = service;
}
public ActionResult AddRecord(Object _Model, String Caller) {
if (service.Add(_Model)) {
TempData["Result"] = "Data Added";
return RedirectToAction(Caller);
}
TempData["Result"] = "Please try again";
return View (Caller, _Model);
}
}
When I wanna use the controller with the DI, I do: (Is this the right way to consume the DataController)
public class TestController: Controller {
public ActionResult Index () {
return View();
}
public ActionResult TestIt (EmployeeModel _Model) {
DataController DC = new DataController(new Employee());
return DC.AddRecord(_Model, "../Test/TestIt");
}
}
You have the general concept of Dependency Injection / Inversion down. That is, you've understood that instead of this:
public class Example {
public void SomeFunc() {
var service = new Service();
service.DoStuff();
}
}
..you do this:
public class Example {
private readonly IService _service;
public Example(IService service) {
_service = service;
}
public void SomeFunc() {
_service.DoStuff();
}
}
.. and you supply the dependency manually via the calling code.. such as a Controller:
public HomeController : Controller {
[HttpGet]
public ActionResult Index() {
var example = new Example(new Service());
example.SomeFunc();
// .. the rest ..
}
}
So, the first part is Dependency Inversion. You have inverted the dependency chain from being top down to bottom up. The second part (the above code block) is Dependency Injection.
Notice in the above block of code that the Controller has no dependencies injected. This is where Inversion of Control comes in.
Inversion of Control is a pattern where code completely external to the currently running code decides how it functions. In this context, it means some external code - somewhere else - decides how to supply dependencies to your controller.
(Note, I am quite familiar with Ninject - so the below examples are using Ninject. There are plenty of other available DI/IoC containers available)
Ninject is a framework that can help with this (and many others). Ninject has an extension for ASP.NET MVC which automatically builds and supplies controller instances for you - plus your dependencies.
Without providing a full tutorial on using Ninject (which I will leave as an exercise to the OP to Google), the basics of it is this.
You declare a "module" with the configuration for your dependencies. Using the above examples, your module might look like this:
public class YourModule : NinjectModule {
public override void Load() {
Bind<IExample>().To<Example>().InRequestScope();
Bind<IService>().To<Service>().InRequestScope();
}
}
This will wire up all requests for an IExample to an Example, and IService to an instance of a Service. So your Controller would become:
public class HomeController : Controller {
private readonly IExample _example;
public HomeController(IExample example) {
_example = example;
}
[HttpGet]
public ActionResult Index() {
_example.SomeFunc();
// .. the rest ..
}
}
The container (in this case, Ninject) looks at your external code (the YourModule class) and determines what IExample should be. It sees that you've said it should be an instance of an Example class. Example also requires a dependency of type IService. So Ninject will again look at YourModule and determines that it should be an instance of Service. It continues to go down the object hierarchy until it completes the construction of the objects.
Hopefully that makes sense - it is definitely hard to explain these concepts in text.
I haven't viewed this video (I am running off of really really terrible WiFi hotspot while I wait for an internet connection!) so I can't verify it's quality, but a quick Google search turned this up for setting up Ninject and MVC: http://www.youtube.com/watch?v=w_MehI2qBTo
You would definitely benefit from Googling around some Inversion of Control and/or Ninject videos to understand what frameworks like it are for.
It is important to note too that frameworks like Ninject can also control scope. In the example above, I used InRequestScope against the bindings. This means that Ninject will instantiate the dependency at the start of the web request - and dispose of it afterward. This removes the need for you to worry about that.
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
I've successfully implemented Ninject in an MVC3 application, but am running into some trouble doing the same thing with ASP.NET Web Forms. I'm getting null references every time I try to access an injected property in my business layer. After setting breakpoints within the CreateKernel method, as well as several places within the ServiceLocator class, it looks like none of them are ever getting hit, so it's not even loading.
I'm sure I'm just approaching this wrong, but there is very little documentation or info out there for wiring up Ninject in a Web Forms application.
Basically here's what I have so far:
code behind
public class ReviewManager
{
[Inject] private IReviewRepository _reviewRepository { get; set; }
public ReviewManager() { }
public ReviewManager(IReviewRepository reviewRepository)
{
_reviewRepository = reviewRepository;
}
public Review GetById(int id)
{
if (id <= 0) throw new ArgumentException("ID must be greater than zero");
**I get a null reference exception on the next line. _reviewRepository is null**
return _reviewRepository.GetById(id);
}
}
global.asax.cs
public class Global : NinjectHttpApplication
{
protected override IKernel CreateKernel()
{
return ServiceLocator.Kernel;
}
// deleted for brevity
}
ServiceLocator.cs (edited for brevity, the relevant parts are here)
public static class ServiceLocator
{
public static IKernel Kernel { get; set; }
public static ILogger Logger { get; set; }
static ServiceLocator()
{
Kernel = new StandardKernel(new INinjectModule[] {
new LoggerBindings(),
new DataBindings()
});
if (Logger == null)
Logger = Kernel.Get<ILogger>();
}
}
public class LoggerBindings : NinjectModule
{
public override void Load()
{
Bind<ILogger>().To<NLogLogger>();
}
}
public class DataBindings : NinjectModule
{
public override void Load()
{
Bind<IReviewRepository>().To<ReviewRepository>();
}
}
ASP.Net via WebForms does not allow you to manage the lifecycle of all object instances (like MVC does). For example, the framework instantiates page objects. This means you probably can't implement DI in quite the same way as you would in MVC/WPF/Silverlight (the same problem is present in WinForms IIRC). You will likely have to initiate the dependency graph directly in each of your code behinds.
Translation: you will want to call ServiceLocator.Kernel.Get<IReviewRepository> when your page loads (or as lazy-init on the property).
The cool thing about MVC ist that it can run side a side of ASP.NET WebForm pages in the same application. In my opinion the best way to extend ASP.NET WebForms websites is to create new pages using MVC3 and to refactor every page that needs major changes to MVC3.
If this is no option go and use the Ninject.Web extension. It contains a IHttpModule that property injects all web pages and controlls after they are initialized. That way you can property inject the services als have them created by Ninject.
A potential workaround, by changing your DataBindings class as follows:
public class DataBindings : NinjectModule
{
public override void Load()
{
Bind<IReviewRepository>().To<ReviewRepository>();
Bind<ReviewManager>().ToSelf();
}
}
And within your caller, instead of
var rm = new ReviewManager();
Try using
var rm = ServiceLocator.Kernel.Get<ReviewManager>();
I havent tested this code, but i think it'll solve your null reference problem.
I use property injection for pages, masterpages and usercontrols. All my pages, for example, inherit from a base class that overrides RequestActivation method with the following code:
''' <summary>
''' Asks the kernel to inject this instance.
''' </summary>
Protected Overridable Sub RequestActivation()
ServiceLocator.Kernel.Inject(Me)
End Sub
And in each page I declare injectable properties:
<Inject()>
Property repo As IMyRepository
I understand the basics on how to unit test, however I often struggle at finding what meaningful things to test. I believe I have to create a fake implementation and inject into the consumer. I have a service class responsible to subscribing to (using Exchange Web Services (EWS)) Exchange 2010 requesting updates on new mail. In order to decouple my subscribing implementation from the service itself I decided to inject the implementation in the service. Below is what I currently have. I've omitted code dealing specifically communicating with Exchange.
// Not a big fan of having two identical interfaces...
public interface IStreamingNotificationService
{
void Subscribe();
}
public interface IExchangeService
{
void Subscribe();
}
public class StreamingNotificationService : IStreamingNotificationService
{
private readonly IExchangeService _exchangeService;
public StreamingNotificationService(IExchangeService exchangeService)
{
if (exchangeService == null)
{
throw new ArgumentNullException("exchangeService");
}
_exchangeService = exchangeService;
}
public void Subscribe()
{
_exchangeService.Subscribe();
}
}
public class ExchangeServiceImpl : IExchangeService
{
private readonly INetworkConfiguration _networkConfiguration;
private ExchangeService ExchangeService { get; set; }
public ExchangeServiceImpl(INetworkConfiguration networkConfiguration)
{
if (networkConfiguration == null)
{
throw new ArgumentNullException("networkConfiguration");
}
_networkConfiguration = networkConfiguration;
// Set up EWS
}
public void Subscribe()
{
// Subscribe for new mail notifications.
}
}
More specifically, how do I create a meaningful unit test to ensure subscribing works the way it should?
Usually you would use a mocking framework to create a fake exchange and test on this object that Subscribe was indeed called. I usually use Rhino Mocks, and your test would look e.g. like this (there are many ways to implement it):
[Test]
public void SubscribesToExchange()
{
var exchange = MockRepository.GenerateMock<IExchangeService>(); //this is the stub
var service = StreamingNotificationService(exchange); //this is the object we are testing
service.Subscribe();
service.AssertWasCalled(x => x.Subscribe(););
}
Decoupling and injection is always a very good idea in terms of unittesting.
Now you can easily test your StreamingNotificationService class. All you have to do is to test is if construction behaves nice, and if subscribemethod calls your injected (and fake) IExchangeService.