I'm using StructureMap in a web project for DI IOC. It works perfect, but I don't have a clue how to write unit tests with StructureMap.
Should I do this in AssemblyInitialize start Configuration of StructureMap like in global.asax except for datacontext not to use live LinqToSqlDataContext but some memory data like this:
[AssemblyInitialize]
public static void Start()
{
ObjectFactory.Configure(x =>
{
x.For<IDataContext>().HttpContextScoped().Use<MemoryDataContext>()
.Ctor<string>("connectionString")
.Is(ConfigurationManager.ConnectionStrings["DEVConnection"].ConnectionString);
x.For<IDepartamentRepository>().Use<DepartamentDB>();
x.For<IDevelopmentProcess>().Use<DevelopmentProcesses>().OnCreation(c => c.User = Current.CurrentUser);
x.For<IActivityProcess>().Use<ActivitiesProcess>().OnCreation(c=> c.User = Current.CurrentUser);
x.For<IDevDeveloperRepository>().Use<DevDeveloperDB>();
x.For<IDevelopmentRepository>().Use<DevelopmentDB>();
x.For<IActivityRepository>().Use<ActivityDB>();
x.For<IActivityTypeRepository>().Use<ActivityTypeDB>();
x.For<IDevUserRepository>().Use<DevUsersDB>();
x.For<IAttachmentRepository>().Use<AttachmentDB>();
}
);
}
and then use ObjectFactory.GetInstance() testing or how do I do this?
You shouldn't need to use a DI Container in unit tests at all.
A container is something you use to wire components together, but a unit test is a test of each component in isolation.
I agree with Mark. Testability is one of the primary reasons you are likely using a container in the first place.
There are times where creating an integration test for your container setup might be a good idea. For example if you have any behavior in your container configuration you will want to create tests for that behavior. In you container config you set IDataContext's connection string via the configuration manager.
The following code is similar to what I do to test such a setup. Notice I avoid ObjectFactory (static singleton objects have their own problems) and wrap my container setup in a bootstrapper helper class:
[Test]
public void connection_string_should_come_from_application_configuration()
{
var container = new ContainerBootstraper().Container;
var connectionString = container.GetInstance<IDataContext>().ConnectionString
connectionString.ShouldEqual("test project application configuration connection string");
}
Related
Ive written a couple of unit tests while using dependency injection and the httpClient in the .net Core 2.0 framework.
Ive been testing my controllers like this:
var result = await __client.PostAsync("api/production-line/validate-assignment-deadline", null);
But now i wanted to mock an object and after searching a bit on the internet all i could find was to do it like this:
var controller = new ProductionLineController(mockProductionLineProvider);
which is not testing the routing and on top of that i would have to create a lot of objects. so i dont want mock my object in this way.
I would like to be able to replace the service with an mock object i havent found a way to get the IServiceCollection into my unittest method.
I would like to be able to do something like this:
var mockingDate = new DateTime(date.Year, date.Month, date.Day, 12, 00, 00);
__constantsMock.Setup(x => x.GetCurrentDateTime()).Returns(mockingDate);
services.Replace(new ServiceDescriptor(typeof(IConstants), ConstantsMock.Object));
var result = await __client.PostAsync("api/production-line/validate-assignment-deadline", null);
I hope you can help me think of ways to get to a solution that doesnt involve me having to create every object that i would inject normaly.
Thank you in advance
edit:
im indeed doing integration tests, i want to test everything but i need to be able to configure the result coming from a DateTime.Now so i made the constants class with a function to return the datetime.now and im trying to mock/stub the class/function. that way i can test multiple scenario's that could occur.
You are looking at the standard way of mocking; you create stubs for all the dependencies (you need to be able to control all of them!) and create the controller. Being able to mock the DI framework wouldn't really buy you anything; you would still need to provide all the dependencies to the class when you constructed it.
Use mocking libraries like NSubstitute to make it easier; if you feel like you have too many dependencies then I would suspect you need to refactor your design (perhaps that controller does too much).
Note that testing with actual HTTP requests is more of an integration test; you are testing the whole app instead of just one class. In that case you can set up different environments for your program and have one that will set up the injector with whatever extra mocks/test data you need.
Once you start doing something like issuing a request to an action, you're pretty much well outside of unit test territory. What you're doing here is integration testing.
As long as you're doing integration testing, you might as well use TestServer, which will actually give you a much more accurate platform for integration tests. Setting up all the dependencies manually doesn't do anything for you in ensuring that your application actually functions as it should. The full documentation is here, but basically, you just do:
_server = new TestServer(new WebHostBuilder()
.UseStartup<Startup>());
_client = _server.CreateClient();
The return of _server.CreateClient() is actually an instance of HttpClient, so your actual test code doesn't really need to change. However, now you've got a full mockup of all your services and config baked in.
The solution to my problem was as follows:
Make an extra starting class that inherits from your StartUp class
Give that class the following code:
public class UnitTestStartup : Startup
{
public static IServiceProvider ServiceProvider;
public static IServiceCollection Services;
public static Mock<IConstants> ConstantsMock;
public void ConfigureTestingServices(IServiceCollection services)
{
ServiceProvider = base.ConfigureServices(services);
Services = services;
ConstantsMock = new Mock<IConstants>();
services.Replace(new ServiceDescriptor(typeof(IConstants), ConstantsMock.Object));
}
}
Make the ConstantsMock (the service you want to mock) available in your baseclass
Like this:
protected Mock<IConstants> __constantsMock;
__constantsMock = UnitTestStartup.ConstantsMock;
have every unit test class inherit from your baseclass
override the __constantsMock with a new object and you're done
I have a Unit Test project & want to shim-in Stub implementations for the repositories within a Unit of Work class. I would know how to do it using other IoC technologies, but am new to StructureMap.
How do I redefine & substitute a definition from inside my Unit Test project
What does that look like?
I'm having trouble finding good documentation on this.
DEFAULT CONTAINER:
Below is part of the business registry I hope to override.
public ContainerRegistry()
{
Scan(...);
// --------
// UNIT OF WORK
// This is the DEFAULT implementation
For(typeof(IRepository<>)).Use(typeof(GenericRepository<>));
For<IUnitOfWork>().Use<MeasurementContractsUnitOfWork>();
}
FOR UNIT TESTS:
In the unit test project I want IoC to use this instead:
// This is the STUB Implementation
For(typeof(IRepository<>)).Use(typeof(GenericRepositoryStub<>));
THE OBJECTIVE:
The objective is to simply use the container, as normal, but get the STUB shimmed-in AUTOMATICALLY.
var container = IoC.Initialize();
var uow = container.GetInstance<IUnitOfWork>()
I am unsure if this is the right way to do it, but this is how I accomplished my goal. If someone gives a better answer, I will mark theirs as correct:
I created separate IOC Initializer & ContainerRegistry classes within the Unit Test project, like so...
INITIALIZER CLASS:
public static class IoC
{
public static IContainer Initialize()
{
var container = new Container();
// NOTE: If you have many Registries to consider, you can add them (order matters)
// The Business Registry
container.Configure(x => x.AddRegistry<Business.DependencyResolution.ContainerRegistry>());
// The UnitTest Projects Registry (order matters)
container.Configure(x => x.AddRegistry<ContainerRegistry>());
return container;
}
}
REGISTRY CLASS:
public class ContainerRegistry : Registry
{
public ContainerRegistry()
{
// The Override
For(typeof(IRepository<>)).Use(typeof(GenericRepositoryIdentifiableStub<>));
}
}
Consider this class with these two constructors:
public class DocumentService
{
private IDocumentDbService documentDbService;
private IDirectoryService directoryService;
private IFileService fileService;
// Constructor
public DocumentService()
{
this.documentDbService = new DocumentDbService();
this.directoryService = new DirectoryInfo();
this.filService = new FileInfo();
}
// Injection Constructor
public DocumentService(IDocumentDbService dbs, IDirectoryService ds, IFileService fs)
{
this.documentDService = dbs;
this.directoryService = ds;
this.fileService = fs;
}
}
I use the second constructor to mock the dependencies for unit testing.
Some times there are too many dependencies, so the injection constructor would have too many parameters.
So, I want to use Unity dependency injection.
Question
How can I refactor this code to use Unity instead?
(After reading Unity documents, still not sure how to use it correctly on my codes.)
Assuming you want to simplify unit test code to avoid manually setting up each dependency in every test:
You can setup container and add all necessary mocks there and than Resolve you class for the test like:
// that initialization can be shared
var container = new UnityContainer();
// register all mocks (i.e. created with Moq)
container.RegisterInstnce<IDocumentDbService>(Mock.Of<IDocumentDbService> ());
// resolve your class under test
var documentService = container.Resolve<DocumentService>();
Assert.AreEqual(42, documentService.GetSomething());
I quess you want to inject dependencies in both situations: in (unit)tests (e.g. using RhinoMocks) and real implementation (using Unity). The refactoring implies in that case that you should remove the the first constructor (of class DocumentService). Needed configuration in your dependencies should be loaded inside the dependency itself: DocumentDbService, DirectoryInfo, FileInfo. More information (like Dependency Injection Lifecycle) and some examples are available on MSDN, see https://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx
I've got a controller with a lot of constructor injection:
public MoviesController(ISession session, IClientContext clientContext, PManager pManager, ISegmentationService segmentationService, IGeoLocator geoLocator, IBus bus)
{
_session = session;
_clientContext = clientContext;
_pManager = pManager;
_segmentationService = segmentationService;
_geoLocator = geoLocator;
_bus = bus;
}
From my understanding (just read about Mocking), I've got a lot of Mock object properties to manually set if I wish to make a comprehensive test suite based on this controller.
For one method I'm only using one service (I'd even like to automate that with little effort if possible):
public object Show(Guid id)
{
var movie = _session.Get<movie>(id);
return movie;
}
But in another there are many services being used - is there any way to set those Moq objects up quickly? I could really use some examples as I'm new to testing. It's an asp.net mvc project with webapi 1 bundled in (testing the webapi controller here)
As has been said in the comments, if you have common setup code, you can put it in a Setup method that is called automatically from your testing framework before each test. It's decorated with a Setup attribute if you're using Nunit TestInitialize if you're using MStest. If you're using XUnit then it's a bit different.
So, your class might look like this:
public class SomeTests {
Mock<ISession> _sessionMock;
Mock<IClientContext> _clientContextMock;
[Setup]
public void Setup() {
_sessionMock = new Mock<ISession>();
_clientContextMock = new Mock <IClientContext();
}
MovieController CreateSut() {
return new MovieController(_sessionMock.Object, _clientContextMock.Object, ...);
}
[Test]
public void TestSomething() {
_sessionMock.Setup(x=>...);
//...
var sut = CreateSut();
//...
}
}
If you're trying to get away from completely creating the mocks manually, then you might want to look at something like AutoFixture with AutoMoq. Which will automatically supply mock instances when creating objects that accept interfaces. AutoFixture can be quite useful, but there is a learning curve to using it effectively so you might want to look at a tutorial / quickstart.
You could also configure an IOC container to supply mock instances for your test project, although I've never gone down that route myself.
For your example, you only need to mock the session, and can leave all the other dependencies null, since their behaviour should be irrelevant to the behaviour you are testing:
Mock<ISession> mockSession = new Mock<ISesssion>();
MoviesController controller = new MoviesController(mockSession.Object, null,null,null,null,null);
There is no need for you to set up any mocks other than the ones you need for this particular test
Currently I have Windsor controller factory that is working well. However, I am changing my controllers a bit and having Windsor instantiate more data for controllers. I forgot to update my Installer class and it failed.
Thus, I realized this is a perfect instance for unit testing, so every time I run my unit tests it will verify that Windsor is set up correctly.
Thus I created the following unit test:
[TestMethod]
public void Windsor_Can_Resolve_HomeController_Dependencies()
{
// Setup
WindsorContainer container = new WindsorContainer();
// Act
HomeController controller = (HomeController)container.Kernel.Resolve(typeof(HomeController));
}
This is exactly the same code that exists in my WindsorControllerFactory.GetControllerInstance() method so I am not sure why this isn't working. When this runs I get:
Test method MyApp.Tests.Controllers.HomeControllerTest.Windsor_Can_Resolve_HomeController_Dependencies threw exception:
Castle.MicroKernel.ComponentNotFoundException: No component for supporting the service MyApp.Controllers.HomeController was found
I'm not sure how to tackle this. The only thing I can think of is that since it's in my test project, and not my Asp.net MVC project it might not be automatically picking up my CommandAndQueryInstaller class, which contains all of my windsor type registration.
Any advice for unit testing windsor dependency configuration?
You are creating a new WindsorContainer in your setup and not registering any dependencies in the container. You'll need to run your IWindsorInstallers in order to populate the container.
[TestMethod]
public void Windsor_Can_Resolve_HomeController_Dependencies()
{
// Setup
WindsorContainer container = new WindsorContainer();
container.Install(FromAssembly.Containing<HomeController>());
// Act
HomeController controller = container.Resolve<HomeController>();
}
Note that you don't have to access the kernel. You can use container.Resolve<T>(), which also takes care of the cast internally.