Unit Testing a Delegate Factory with Autofac - c#

I'm working on proving out using Dependency Injection with some numerous DI frameworks. I'm attempting to try to unit test some classes currently using Autofac as the DI container.
Let's say I have this class...
public class SaveUserCommand : DBCommandBase<UserImpl>
{
public delegate SaveUserCommand Factory(UserImpl impl);
private UserImpl impl;
private IAuditableHelper helper;
public SaveUserCommand(UserImpl impl, IAuditableHelper helper)
{
this.impl = impl;
this.helper = helper;
}
public override UserImpl Execute(object dataTrans)
{
return this.impl;
}
}
^Command structured business layer btw.
I have another command that relies on the above command in this way...
public class SaveSpecialUserCommand : DBCommandBase<UserImpl>
{
public delegate SaveSpecialUserCommand Factory(UserImpl user);
private UserImpl user;
SaveUserCommand.Factory saveUserCommand;
public SaveSpecialUserCommand(UserImpl user, SaveUserCommand.Factory saveUserCommand)
{
this.user = user;
this.saveUserCommand = saveUserCommand;
}
public override UserImpl Execute(object dataTrans)
{
this.user.IsSpecial = true;
this.saveUserCommand(this.user).Execute(dataTrans);
return this.user;
}
}
Using Autofac, it resolves all dependencies in the SaveSpecialUserCommand.
What I am unsure of, is how I can unit test or inject a mock into the SaveUserCommand.Factory delegate.
Hints would be good. I still want to figure this out, but a general direction would be awesome.
EDIT
Just adding a simple test case showing I do not want to use Autofac in my unit tests to create my commands.
[Test]
public void SomeSimpleTestTest()
{
var user = new UserImpl();
var command = new SaveSpecialUserCommand(user, /*This is what I need to mock. SaveUserCommand.Factory*/null);
var retVal = command.Execute(this._mockTransaction);
Assert.IsNotNull(retVal);
Assert.IsTrue(retVal.IsSpecial);
}

If you resolve SaveSpecialUserCommand through the container, you can't mock the factory delegate since this is a piece that Autofac autogenerates for you. The question is then, why do you need to fake the actual delegate?
Update: bit of misunderstanding initially there. To "fake" a delegate you can simply use a lambda, like this:
var user = new UserImpl();
var cmd = new SaveUserCommand(...);
var command = new SaveSpecialUserCommand(user, u => cmd);

Related

Why is my unit test failing for a switch statement?

Hi I am trying to unit test the following and check that this switch/case statement works:
DiagnosticsComponentFactory class
private readonly IServiceProvider _serviceCollection;
public IComponent Create (string name)
{
switch (name)
{
case BoardItemComponent.TypeName:
return _serviceCollection.GetService<BoardItemComponent>();
default:
throw new NotSupportedException();
}
}
My BoardItemComponent class:
public class BoardItemComponent
{
public const string TypeName = "name";
public BoardItemComponent(IConfigurationRepository configurationRepository) : base(configurationRepository)
{
}
}
BoardItemComponent is derived from IComponent, and it's added like follows in my Startup.cs file:
services.AddScoped<IComponent, BoardItemComponent>();
my unit test:
[Test]
public void GetComponent_GivenComponentFactory_ExpectBoardComponent()
{
var serviceCollection = new ServiceCollection();
ComponentFactoryRegistration.Register(serviceCollection);
var factory = new DiagnosticsComponentFactory(serviceCollection.BuildServiceProvider());
var component = factory.Create("name");
Assert.IsNotNull(component);
}
When I debug my unit test, component is null, despite it following all the correct steps. It goes into the switch case statement correctly and recognizes that is the correct case, however it still returns null.
From what I have shared (and apologies, as I know that the names in these code snippets are vague without context), is there any obvious reason that my unit test fails? I'm new when it comes to unit testing in C#.
Based on your comments you indicated that the component is registered as
services.AddScoped<IComponent, BoardItemComponent>();
The provider is aware of the IComponent interface, but is asking for BoardItemComponent implementation
_serviceCollection.GetService<BoardItemComponent>();
The above will return null if the provider is unaware how to resolve BoardItemComponent when explicitly requested.
Register the implementation
services.AddScoped<BoardItemComponent>();
and you can also associate it with the abstraction using the factory delegate
services.AddScoped<IComponent>(sp => sp.GetRequiredService<BoardItemComponent>());
Isolated testing should now be able to be done accordingly
[Test]
public void GetComponent_GivenComponentFactory_ExpectBoardComponent() {
//Arrange
var serviceCollection = new ServiceCollection();
serviceCollection.AddScoped<BoardItemComponent>();
serviceCollection.AddScoped<IConfigurationRepository>(sp => Mock.Of<IConfigurationRepository>());
var factory = new DiagnosticsComponentFactory(serviceCollection.BuildServiceProvider());
//Act
var component = factory.Create(BoardItemComponent.TypeName);
//Assert
Assert.IsNotNull(component);
}
Now it was indicated that there may be more implementation in the future.
Lets say for example
services.AddScoped<BoardItemComponent>();
services.AddScoped<AnotherItemComponent>();
The factory can then be refactored
public class DiagnosticsComponentFactory {
private readonly IServiceProvider services;
public DiagnosticsComponentFactory (IServiceProvider services) {
this.services = services;
}
public IComponent Create (string name) {
switch (name) {
case BoardItemComponent.TypeName:
return services.GetRequiredService<BoardItemComponent>();
case AnotherItemComponent.TypeName:
return services.GetRequiredService<AnotherItemComponent>();
default:
throw new NotSupportedException();
}
}
}

Override Autofac registration - Integration tests with DI

I write integration tests for my application, and use my container for this. I want to be able to register all the components as I do in real running, and then override some of the components and switch them to use stubs implementations.
I wouldn't want to seperate the DI and have a container for tests only because I want to test the real thing.
Doing this also seems ugly:
public class MyRegistrations
{
public static RegisterAll(bool isInTest= false)
{
if (isTest)
{
// Register test fakes
}
else
// Register real components
}
}
So I thought of overriding registrations in my test enviorment. How should it be done?
Any other better ways for achieving my goal?
Thanks
Autofac will use the last registered component as the default provider
of that service
From the AutoFac documation.
In your arrange/setup/testInit phase register the mocks, then resolve the SUT:
[SetUp]
public void TestInit()
{
Mock<IFoo> mock = new Mock<IFoo>();
builder.RegisterInstance(mock.object).As<IFoo>();
...
...
_target = builder.Resolve<The component>();
}
Note:
Singletons, static members and SingletonLifestyle(registration) may cause some troubles....
Well, for example you can create a static action method inside your composition root to alter the current configuration and call it during testing. For example:
public class CompositionRoot
{
public static Action<IContainer> OverrideContainer = c => { };
internal static IContainer CreateContainer()
{
ContainerBuilder builder = new ContainerBuilder();
/// etc. etc.
var container = builder.Build();
OverrideContainer(container);
return container;
}
}
After that you can create a mock of you server, for example, like this:
[TestFixture]
public class ConfigurationControllerFixture : BaseServer
{
[Test]
public async Task verify_should_get_data()
{
var response = await GetAsync(Uri);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
protected override string Uri
{
get { return "api/configuration"; }
}
}
public abstract class BaseServer
{
protected TestServer Server;
protected abstract string Uri { get; }
protected virtual void OverrideConfiguration()
{
CompositionRoot.OverrideContainer = c =>
{
// new autofac configuration
cb.Update(c);
};
AppStartup.OverrideConfiguration = c =>
{
// same as explained, but for HttpConfiguration
};
}
}
[SetUp]
public void Setup()
{
OverrideConfiguration();
Server = Microsoft.Owin.Testing.TestServer.Create(app =>
{
var startup = new AppStartup();
startup.Configuration(app);
});
PostSetup(Server);
}
Hope it helps :)
If you want to write integration test from API to database you can use XUnit. XUnit use TestHost and WebApplicationFactory to create a System under test. With XUnit, it's very easy to mock a test service by add test service to service collection.
I made a open source project use XUnit to test my API work with mySQL database. Please visit here for example https://gitlab.com/quorion-group/quorion-backend-crm

Unit Testing with DbContext mock through Service Layer

I'm a beginner at writing unit tests and I have a test I'm trying to get working. I'll start of by explaining what I'm trying to test.
I'm trying to test a method which saves messages in a Mvc 4 project. The method is called SaveMessage and is shown below.
namespace ChatProj.Service_Layer
{
public class UserService : IUserService
{
public MessageContext messageContext = new MessageContext();
public UserService()
{
_messageRepository = new MessageRepository(messageContext);
}
private IMessageRepository _messageRepository;
-> public void SaveMessage(Message message)
{
messageContext.Messages.Add(message);
_messageRepository.Save();
}
The _messageRepository.Save in the SaveMessage method is implemented in my DAL layer MessageRepository and looks like this:
public void Save()
{
context.SaveChanges();
}
This way of saving will seem a bit overcomplicated, but I structured the project this way because I didn't want the service layer (IUserService & UserService) to handle operations that could & should (i think) be handled by the Data Access Layer (IMessageRepository & MessageRepository).
Now comes the tricky part. I've been trying to understand how I could unit test this. This is my try:
namespace ChatProj.Tests
{
[TestFixture]
class MessageRepositoryTests
{
[SetUp]
public void Setup()
{
}
[Test]
public void SaveMessage_SaveWorking_VerifyUse()
{
//Arrange
var userServiceMock = new Mock<UserService>();
var message = new Message { MessageID = 0, Name = "Erland", MessageString = "Nunit Test", MessageDate = DateTime.Now };
var repositoryMock = new Mock<IMessageRepository>();
var contextMock = new Mock<MessageContext>();
MessageRepository messageRepository = new MessageRepository(contextMock.Object);
UserService userService = new UserService();
//Act
userService.SaveMessage(message);
//Assert
repositoryMock.Verify(m => m.Save());
userServiceMock.Verify(m => m.SaveMessage(message));
}
}
I get this error: Imgur link , and I'm not quite sure how to solve it. I've tried looking at several other SO posts but I fail to make the test work.
So I'm wondering, how do I practically get my Unit Test to work?
You should setup your MessageContext properties to return fake data and don't make real Db call with SaveChanges method.
Right now it still tries to access a real DB.
But you can setup only virtual properties or if it will be an inteface.
So the best solution is to extract an interface from your MessageContext and inject it into repository. Then you can easily mock your IMessageContext interface and force it to return appropriate in-memory data.
Take a look at these two lines:
UserService userService = new UserService();
//Act
userService.SaveMessage(message);
You're creating a userService instance, and then immediately saving your message. Now jump into the SaveMessage code.
public void SaveMessage(Message message)
{
messageContext.Messages.Add(message);
_messageRepository.Save();
}
Ok, now you're adding stuff to messageContext, and then calling _messageRepository.Save(). But where are messageContext and _messageRepository instantiated?
public MessageContext messageContext = new MessageContext();
public UserService()
{
_messageRepository = new MessageRepository(messageContext);
}
You're creating them at instantiation. The mocks that you've created in your test aren't being used. Instead of creating instances of these objects in the constructor, you might consider passing them into the UserService constructor as arguments. Then, you can pass in mocked instances in your test.

Automocking the SUT

I have read Mark Seeman's article on auto-mocking and I'm now writing a re-usable windsor container based on that article.
My implementation of Mark's article (basically copied directly)
The main work is done in the AutoMoqResolver class. This will provide a mock whenever a class has a dependency on an interface:
public class AutoMoqResolver : ISubDependencyResolver
{
private readonly IKernel kernel;
public AutoMoqResolver(IKernel kernel)
{
this.kernel = kernel;
}
public bool CanResolve(
CreationContext context,
ISubDependencyResolver contextHandlerResolver,
ComponentModel model,
DependencyModel dependency)
{
return dependency.TargetType.IsInterface;
}
public object Resolve(
CreationContext context,
ISubDependencyResolver contextHandlerResolver,
ComponentModel model,
DependencyModel dependency)
{
var mockType = typeof(Mock<>).MakeGenericType(dependency.TargetType);
return ((Mock)this.kernel.Resolve(mockType)).Object;
}
}
The AutoMoqResolver is added to the container using the following implementation of the IWindsorInstaller interface:
public class AutoMockInstaller<T> : IWindsorInstaller
{
public void Install(
IWindsorContainer container,
IConfigurationStore store)
{
container.Kernel.Resolver.AddSubResolver(
new AutoMoqResolver(container.Kernel));
container.Register(Component.For(typeof(Mock<>)));
container.Register(Classes
.FromAssemblyContaining<T>()
.Pick()
.WithServiceSelf()
.LifestyleTransient());
}
}
Then my container simply runs the installer and it is ready to automatically provide mocks for any interface dependencies in unit tests:
public class AutoMockContainer<T> : WindsorContainer
{
public AutoMockContainer()
{
// simply run the auto-mock installer
this.Install(new AutoMockInstaller<T>());
}
}
Super!
I've tested this and my dependencies are happily mocked automatically so I then went to apply it to some real code. This is when I realised that the solution doesn't help me because of the pattern I tend to follow when testing a class. My specific issue is that I want to be able to auto-mock the SUT itself in order to verify that one method on the SUT is called from another.
My code that needs to be tested
I'll explain myself by way of an example. I am developing MVC code and I am supporting unobtrusive AJAX using the following general pattern:
public Class ExampleController : Controller
{
private IService service;
public ExampleController(IService service)
{
this.service = service;
}
public PartialViewResult DoSomethingWithAjax()
{
this.PerformTask();
return this.PartialView();
}
public RedirectToRouteResult DoSomethingWithoutAjax()
{
this.PerformTask();
return this.RedirectToAction("SomeAction");
}
protected virtual void PerformTask()
{
// do something here
}
}
My test pattern
So in order to verify that the PerformTask() method was called from DoSomethingWithAjax() or DoSomethingWithoutAjax(), I define a new TestableExampleController class like this:
public class TestableExampleController : ExampleController
{
public TestableExampleController(IService service) : base(service)
{
}
public virtual void PerfomTaskPublic()
{
base.PerfomTask();
}
protected override void PerformTask()
{
this.PerformTaskPublic();
}
}
I can then use TestableExampleController as my SUT so the following test will pass:
[TestMethod]
public void DoSomethingAjax_Calls_PerformTask()
{
//// Arrange
// create a mock TestableExampleController
var controllerMock = new Mock<TestableExampleController>();
controllerMock.CallBase = true;
// use the mock controller as the SUT
var sut = controllerMock.Object;
//// Act
sut.DoSomethingAjax();
//// Assert
controllerMock.Verify(x => x.PerformTaskPublic(), Times.Once());
}
My problem
Refactoring this test to use my AutoMockContainer class like this doesn't work:
[TestMethod]
public void DoSomethingAjax_Calls_PerformTask()
{
//// Arrange
// create a container
var container = new AutoMockContainer<TestableExampleController>();
// resolve a mock SUT using the container
var controllerMock = container.Resolve<Mock<TestableExampleController>>();
controllerMock .CallBase = true;
// use the mock controller as the SUT
var sut = controllerMock.Object;
//// Act
sut.DoSomethingAjax();
//// Assert
controllerMock.Verify(x => x.PerformTaskPublic(), Times.Once());
}
The test fails to create an instance of Mock<TestableExampleController> because it can't find a parameterless constructor.
Can not instantiate proxy of class: MyNamespace.TestableExampleController.
Could not find a parameterless constructor.
Parameter name: constructorArguments
My proposed solution
Ideally I would like to implement a wrapper class which can be registered with the container to automatically provide a mock for any component:
public class ComponentWrapper<T> where T : class
{
public ComponentWrapper(Mock<T> componentMock)
{
componentMock.CallBase = true;
this.ComponentMock = componentMock;
}
public Mock<T> ComponentMock { get; private set; }
public T Component
{
get { return this.ComponentMock.Object; }
}
}
I would like to be able to write the following test that passes:
[TestMethod]
public void DoSomethingAjax_Calls_PerformTask()
{
//// Arrange
// create a container
var container = new AutoMockContainer<TestableExampleController>();
// resolve a ComponentWrapper using the container
var wrapper = container.Resolve<ComponentWrapper<TestableExampleController>>();
//// Act
// call a method using the component
wrapper.Component.DoSomethingAjax();
//// Assert
// verify a method call using the mock
wrapper.ComponentMock.Verify(x => x.PerformTaskPublic(), Times.Once());
}
I can't quite get my head round how to achieve this and I've spent most of the day fiddling with new ISubDependencyResolver implementations but I just can't get this to work.
Hopefully my question is clear and the answer is actually relatively simple?
It turns out that AutoFixture.AutoMoq will do exactly what I want out of the box so thank you to TrueWill for pointing me in the right direction.
The following simple test will pass:
[TestMethod]
public void Run_Calls_DoSomethingProtected()
{
//// Arrange
// AutoMoqCustomization allows AutoFixture to
// be used an an auto-mocking container
var fixture = new Fixture().Customize(new AutoMoqCustomization());
// simply ask the fixture to create a mock
var sutMock = fixture.Create<Mock<TestableDummySystem>>();
//// Act
// exercise the mock object
sutMock.Object.Run();
//// Assert
// this verification passes!
sutMock.Verify(x => x.DoSomethingProtectedPublic());
}

How to create a Moq provider for Ninject?

I want to create a simple Ninject provider that returns Moq'd instances instead of concrete types. So far I have this:
public class NinjectMockProvider<T> : IProvider
{
public static Type Type { get { return typeof(T); } }
public object Create(IContext context)
{
Mock<T> newMock = new Mock<T>();
return newMock.Object;
}
}
But this is all wrong I'm sure as I don't know what I'm doing really. Any help and code samples would be great. I just want the ability to do:
kernel.Bind<ISomeInterface>().ToProvider<NinjectMoqProvider<ISomeInterface>>();
or something to that effect.
Update
I did figure out that I could accomplish what I want by using Ninject's method binding:
kernel.Bind<ISomeInterface>().ToMethod(x => new Mock<ISomeInterface>().Object);
I still would like a more elegant way and I may have to check out Ninject.Moq as suggested by Ian, but if anyone has any real code examples that would be awesome.
Does the MockingKernel extension handle what you need? It has Moq, RhinoMocks, and NSubstitute flavors, and it is also available on NuGet.
My solution to this always just uses the following:
MoqProvider
public class MoqProvider<T> : Provider<T> // T is the desired service
{
protected override T CreateInstance(IContext context)
{
return new Mock<T>().Object;
}
}
I then also register an IMissingBindingResolver with my kernel. The MoqMissingBindingResolver simply creates a new binding to a MoqProvider for any service for which a binding does not already exist.
MoqMissingBindingResolver
public class MoqMissingBindingResolver : NinjectComponent, IMissingBindingResolver
{
public IEnumerable<IBinding> Resolve(Multimap<Type, IBinding> bindings, IRequest request)
{
if (request.Service.IsAbstract || request.Service.IsInterface)
{
var moqProvider = (IProvider)Activator.CreateInstance(typeof(MoqProvider<>).MakeGenericType(request.Service));
return new IBinding[]
{
new Binding(request.Service, new BindingConfiguration
{
ProviderCallback = ctx => moqProvider,
ScopeCallback = Settings.DefaultScopeCallback
})
};
}
else
{
return Enumerable.Empty<IBinding>();
}
}
}
I typically also set Settings.DefaultScopeCallback to singleton so that I can request my mocked objects in my tests later on when I need to verify certain calls have or haven't taken place, or setup behaviour on mocks prior to executing the test. So setting up my kernel will look like the following:
INinjectSettings Settings = new NinjectSettings
{
DefaultScopeCallback = StandardScopeCallbacks.Singleton
};
var k = new StandardKernel(Settings);
k.Components.Add<IMissingBindingResolver, MoqMissingBindingResolver>();
Hope this is helpful.

Categories

Resources