10

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?

davidsleeps
  • 8,999
  • 11
  • 57
  • 73
Florim Maxhuni
  • 1,395
  • 1
  • 17
  • 34

2 Answers2

21

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.

Community
  • 1
  • 1
Mark Seemann
  • 209,566
  • 41
  • 390
  • 671
  • I agree with that, but what If I have one class that consumes multiple instances, all I would swap using DI is let say DAL to use in memory repository. If my constructor takes 10 interfaces then I need to provide 10 instances manually while using DI, all done automatically. Even if I would create a composition of 10 interfaces into one, I still need to mock it somehow... – Pawel Cioch Feb 09 '16 at 22:12
  • 1
    @PawelCioch If your constructor takes ten dependencies, it's [probably doing too much](http://stackoverflow.com/a/2420245/126014). Not only is this a design smell, it's also likely that it will be difficult to test, or at least to maintain the tests. – Mark Seemann Feb 10 '16 at 06:26
  • I guess I gotta change the job to work with simpler projects :). The class that takes all those is final Service for console app that needs all kinds of repositories and filters. Probably could re-factor but the algorithms are so interconnected that is hard to isolate unit of work. Anyhow thanks for feedback. – Pawel Cioch Feb 10 '16 at 15:35
6

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");
}
KevM
  • 2,406
  • 1
  • 21
  • 25
  • Would it be a bad idea to point the `ShouldEqual` comparison directly to the AppSettings value in question in this case? I won't pretend to have a clue when it comes to unit testing best practices, but as I was reading this I kept thinking it didn't seem to be confirming that it came from configuration. – patridge Feb 12 '10 at 15:53
  • Sorry, my example was very terse. I was assuming that the test setup would have given the context necessary. The setup would be responsible for making sure that application setting was present. – KevM Feb 12 '10 at 16:57
  • Any chance you can post a sample of what you're doing with that Bootstrapper class? I'm struggling through some of the same challenges, and I'm not quite bright enough to piece this together. – Bobby B Aug 21 '15 at 16:39
  • @BobbyB Here is an example I have in a public repo: https://github.com/DovetailSoftware/dovetail-bootstrap/blob/master/source/Dovetail.SDK.ModelMap.Integration/Session/bootstrap_ioc.cs – KevM Jan 20 '16 at 16:19