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());
}
Related
I have the following setup:
A calendar controller that calls a calendar service that calls a calendar client wrapper that calls the client. Controller -> Service -> ClientWrapper -> Client.
I am making an integration test that mocks the lowest tier (the client) and calls the controller to see if the client was called correctly.
My CalendarControllerBuilder:
internal class CalendarControllerBuilder
{
public CalendarControllerBuilder()
{
CalendarClientMock = new Mock<ICalendarServiceClient>(MockBehavior.Strict);
}
public Mock<ICalendarServiceClient> CalendarClientMock { get; set; }
public CalendarControllerBuilder With(Mock<ICalendarServiceClient> calendarClientWrapperMock)
{
CalendarClientMock = calendarClientWrapperMock;
return this;
}
public CalendarController Create()
{
var calendarClientWrapperMock = new CalendarClientWrapper(CalendarClientMock.Object);
var calenderService = new CalendarService(calendarClientWrapperMock);
return new CalendarController(calenderService);
}
}
Test setup with customization registration:
internal class CalenderControllerCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Register<CalendarController>(() =>
{
// ----- ICalendarServiceClient mock setups -----
var calendarServiceClientMock = new Mock<ICalendarServiceClient>(MockBehavior.Strict);
calendarServiceClientMock.Setup(m => m.GetEvents(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(fixture.Create<EventList>()).Verifiable();
return new CalendarControllerBuilder()
.With(calendarServiceClientMock)
.Create();
});
}
}
My automoq data attribute (using AutoFixture.Xunit2):
public class Attributes
{
public class AutoMoqDataAttribute<T> : AutoDataAttribute where T : ICustomization, new()
{
public AutoMoqDataAttribute()
: base(() => new Fixture()
.Customize(
new CompositeCustomization(
new AutoMoqCustomization(),
new T())))
{
}
}
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute()
: base(() => new Fixture()
.Customize(
new AutoMoqCustomization()))
{
}
}
}
My test that works fine and uses the customization registration:
[Theory]
[AutoMoqData<CalenderControllerCustomization>]
public async Task Test_GetAllEvents_ClientIsCalledCorrectlyAndReturnsCorrectData(
IFixture fixture,
[Frozen] Mock<ICalendarServiceClient> calendarServiceClientMock,
CalendarController sut)
{
// Arrange
var startDate = fixture.Create<DateTimeOffset>();
var endDate = fixture.Create<DateTimeOffset>();
// Act
var eventList = await sut.GetAllEvents(startDate, endDate);
// Assert
eventList.Events.Count.Should().Be(3); // fixture always create 3 of lists here
calendarServiceClientMock.Verify();
}
THE PROBLEM:
Now I want to override the setup with my own data returned.
[Theory]
[AutoMoqData<CalenderControllerCustomization>]
public async Task Test_GetAllEvents_ClientIsCalledCorrectlyAndReturnsCorrectData_Overridden(
IFixture fixture,
[Frozen] Mock<ICalendarServiceClient> calendarServiceClientMock,
CalendarController sut)
{
// Arrange
var startDate = fixture.Create<DateTimeOffset>();
var endDate = fixture.Create<DateTimeOffset>();
var result = fixture.Build<EventList>()
.With(x => x.Events, fixture.CreateMany<Event>(5).ToList())
.Create();
// override client mock setup:
calendarServiceClientMock.Setup(m => m.GetEvents(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(fixture.Build<EventList>()
.With(x => x.Events, fixture.CreateMany<Event>(5).ToList())
.Create()).Verifiable();
// Act
var eventList = await sut.GetAllEvents(startDate, endDate);
// Assert
eventList.Events.Count.Should().Be(5); // FAILS - IT GETS 3 AND NOT 5
calendarServiceClientMock.Verify(); // THIS FAILS TOO IF I SET 3 IN ABOVE
}
I have tried with and without the Frozen attribute.
What am I missing here? I don't want to call my calendarcontroller builder as the point is to avoid boilerplate. Do I need a registration of the client or something else I'm missing
(maybe related to Override Autofixture customization setup but using moq and not n-subtitute. Could not get this to work even with correct order of parameters)
Thanks for reading!
With the current way you customize the fixture I don't think you can. By creating a custom builder and instantiating the mock by hand you've basically painted yourself in a corner.
To get AutoFixture to control the instances you need in the test, you must allow it to generate them. Here's a possible solution.
The root of your SUT is the controller. Let's say it receives as a parameter an ICalendarService that's always the concrete implementation CalendarService.
To tell AutoFixture that the implementation is always a concrete type you can relay the resolved type to the concrete implementation.
fixture.Customizations.Add(new TypeRelay(typeof(ICalendarService), typeof(CalendarService)));
Next the service takes as a constructor parameter an abstraction that's ICalendarClient which is resolved as the wrapper but only for the service. This means you have to identify the constructor parameter and relay the request to the wrapper type.
fixture.Customizations.Add(new FilteringSpecimenBuilder(
new FixedRequestRelay(typeof(CalendarClientWrapper)),
new YourConstructorParameterSpecification()));
The YourConstructorParameterSpecification is a IRequestSpecification implementation that identifies a request as a parameter of type ICalendarClient that belongs to the constructor of type CalendarService.
FixedRequestRelay is a simple ISpecimenBuilder that always resolves the same predefined request from ISpecimenContext instead of the received one.
Here's a very basic implementation of it.
public record FixedRequestRelay(object Request) : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
=> context.Resolve(this.Request);
}
Next you have your wrapper that also takes as a parameter an abstraction of type ICustomerClient. However this instance you want to be resolved as a mock that you can control from the test. Since you use AutoFixure.AutoMoq you can leave this one as is and let AutoMoq generate a mock for it.
Let's say this is the resulting customization.
public class CalendarCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new TypeRelay(typeof(ICalendarService), typeof(CalendarService)));
fixture.Customizations.Add(new FilteringSpecimenBuilder(
new FixedRequestRelay(typeof(CalendarClientWrapper)),
new AndRequestSpecification(
new ParameterSpecification(typeof(ICalendarClient), "client"),
new ParameterMemberSpecification(
new DeclaringTypeSpecification(
new ExactTypeSpecification(typeof(CalendarService)))))));
}
}
By using it you can write a test like this.
[Theory, MyData]
public async Task Foo(
[MinLength(5)] Event[] events,
[Frozen] Mock<ICalendarClient> clientMock,
CalendarController controller,
DateTime start, DateTime end)
{
clientMock
.Setup(x => x.GetAllEvents(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(events);
var actual = await controller.GetAllEvents(start, end, default);
Assert.Equal(events, actual);
}
public List<CustomerViewModel> GetResellerCustomersWithProperties(string shortCode)
{
var businessManager = DependencyContainer.GetInstance<ICortexBusinessManager>();
return businessManager.GetResellerCustomersWithProperties(shortCode);
}
How do we write Test case using Nunit which has a dependency from interfaces.
Dependency Injection is your friend here.
Note You will need an IOC container, such as Autofac, Unity, StructureMap etc... wired up with your application.
Inject your dependencies in the constructor of your class:
public class CustomerService
{
private ICortexBusinessManager _cortexBusinessManager;
public CustomerService (ICortexBusinessManager cortexBusinessManager)
{
_cortexBusinessManager = cortexBusinessManager;
}
public List<CustomerViewModel> GetResellerCustomersWithProperties(string shortCode)
{
return _cortexBusinessManager.GetResellerCustomersWithProperties(shortCode);
}
}
You can then use a mocking framework within your unit test to mock calls to your interface.
Example below uses Moq
public class CustomerServiceTest
{
[Test]
public void GetResellerCustomersWithProperties_ReturnsFromCortextBusinessManager()
{
//arrange
var mockCortexBusinessManager = new Mock<ICortexBusinessManager>();
//if GetResellerCustomersWithProperties is called with s123, return a new list of CustomerViewModel
//with one item in, with id of 1
mockCortexBusinessManager.Setup(m=> m.GetResellerCustomersWithProperties("s123"))
.Returns(new List<CustomerViewModel>(){new CustomerViewModel{Id = 1}});
var customerService = new CustomerService(mockCortexBusinessManager.Object);
//act
var result = customerService.GetResellerCustomersWithProperties("s123");
//assert
Assert.AreEqual(1, result.Count())
Assert.AreEqual(1, result.FirstOrDefault().Id)
}
}
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
I have a simple contoller of a standard MVC 5 web application. I installed the MVC 5 Ninject nuget package. I created a constructor and the interface that I have defined is injected. If I create a public property this is also injected.
Now when I create a unittest project and want to test the mvc controller. How can I do that? I have to create a kernel. The kernel is created and if I get an instance of my IPersonComponent it is created. But why doesn't my property not get injected?
I created two options and both I get nullreference exception...
Interface:
public interface IPersonComponent
{
void DoSomething();
}
Implementation:
public class PersonComponent : IPersonComponent
{ public void DoSomething()
{
throw new NotImplementedException("The method is fired but not implemented");
}
}
TestInitialize:
private IKernel _kernel;
[TestInitialize()]
public void Initialize()
{
_kernel = new StandardKernel();
}
Option 1
Controller that is working great:
public class HomeController : Controller
{
private readonly IPersonComponent _component;
public HomeController(IPersonComponent component)
{
_component = component;
}
}
Unittest fails because PersonComponent is null:
[TestClass]
public class HomeControllerTest
{
[Inject]
public IPersonComponent PersonComponent { get; set; }
[TestMethod]
[ExpectedException(typeof(NotImplementedException))]
public void Index()
{
// Arrange
HomeController controller = new HomeController(PersonComponent);
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
Assert.IsNotNull(result);
}
}
Option 2
Controller:
public class HomeController : Controller
{
[Inject]
public IPersonComponent PersonComponent { get; set; }
public HomeController()
{
}
public ActionResult Index()
{
PersonComponent.DoSomething();
return View();
}
}
Test:
[TestMethod]
[ExpectedException(typeof(NotImplementedException))]
public void Index()
{
// Arrange
HomeController controller = new HomeController();
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
Assert.IsNotNull(result);
}
This works:
But why does it work? Why isn't it injected automatically?
[TestMethod]
public void TestDoSomething()
{
var kernel = new StandardKernel();
var comp = kernel.Get<IPersonComponent>();
comp.DoSomething();
}
Edit based on the answer:
Option 1
[TestMethod]
[ExpectedException(typeof(NotImplementedException))]
public void Index()
{
_kernel.Inject(this);
// Arrange
HomeController controller = new HomeController(PersonComponent);
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
Assert.IsNotNull(result);
}
Option 2
[TestMethod]
[ExpectedException(typeof(NotImplementedException))]
public void Index()
{
// Arrange
HomeController controller = _kernel.Get<HomeController>();
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
Assert.IsNotNull(result);
}
In option 1: MsTest does not invoke Ninject to tell it to inject services into your objects.
In option 2: You are creating the controller manually (new HomeController()), and you're not telling Ninject to inject services into your objects.
Although much of what Ninject does seems "magical," it still has to be invoked in order to be able to inject values into your components. ASP.NET MVC has a mechanism that Ninject ties itself into, so that construction of controllers is handled by Ninject automatically. This gives you the impression that Ninject is able to inject values into anything without effort. But MSTest does not have a similar mechanism, so you have to do some of this work manually.
If you have access to the ninject kernel that's been configured, you can say:
HomeController controller = kernel.Get<HomeController>();
Or, in option 1, you can say:
public HomeControllerTest()
{
kernel.Inject(this); // populate my [Inject] properties
}
I should mention that if you're injecting dependencies based on real bindings, you're not really writing "unit tests," but rather "automated acceptance tests." If you want to test the behavior of a controller action independent of its dependencies, learn how to "mock" its dependencies instead.
I am using Castle Windsor for IOC and Fluent NHibernate for an ORM. I am creating Integration Tests to verify mappings and basic functionality. How do I get access to an object instantiated by Castle Windsor?
Here is my repository installer:
public class RepositoryInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IContainerRepository>().ImplementedBy<ContainerRepository>().LifestylePerWebRequest());
}
}
Here is my repository:
public interface IContainerRepository
{
IEnumerable GetActiveContainers();
}
public class ContainerRepository : BaseRepository, IContainerRepository
{
public ContainerRepository(ISession session)
: base(session)
{
}
public IEnumerable<Container> GetActiveContainers()
{
var query = Session.CreateCriteria<Container>()
.Add(Restrictions.Eq("ContentsType", "Raw Material"))
.Add(Expression.Sql("QTY_IN - QTY_OUT > 0"));
return query.List<Container>();
}
}
Here is a simple test that I would like to write:
[Test]
public void GetActiveTest()
{
var repo = **DoSomethingHere**.GetInstance<IContainerRepository>();
var list = repo.GetActiveContainers().ToList();
Assert.IsTrue(list.Count > 0);
}
You are testing two seperate things. Have one set of tests to validate your Windsor installer and another to validate your repository.
When testing your repository, set up your database with appropriate test data and then create a ContainerRepository instance and call GetAllContainers method on it. As you know what test data is in the database, you can then verify what is being returned is appropriate.
[TestFixtureSetup]
public void Init()
{
Fluently.Configure()
.Database(/* examples here */)
.Mappings(...)
.BuildSessionFactory();
}
[TestFixtureTeardown]
public void Cleanup()
{
// tear down the session here...
}
[Test]
public void GetActiveContainer_Returns_Expected_Containers()
{
var sut = new ContainerRepository();
var list = sut.GetActiveContainers().ToList();
Assert.IsTrue(list.Count > 0);
}
Your Windsor container test might look something like this:
[Test]
public void Build_Returns_Container_With_Resolvable_Repo()
{
using (container = ContainerBuilder.Build())
{
var actualContainerRepo = container.Resolve<IContainerRepository>();
Assert.IsNotNull(actualContainerRepo);
}
}