Search code examples
c#inversion-of-controlstructuremap

Force StructureMap to Plug-In a populated Instance During Runtime


During unit tests, I load-up my Unit-of-Work (UOW) instance with mock data. Then, I hand the Unit-of-Work instance to the class-instances that are being tested.

FOR EXAMPLE:
Below I am loading the UOW with default scenario data...and then...setting the UOW into the newly created WorkfklowProvider (instance)

// ARRANGE
var unitOfWork = Builder.CreateInstance<MeasurementContractsUnitOfWork>();

// Load Data
Builder.DefaultDataScenario.Load(unitOfWork);

// at this point...the UOW is full of testable data

// Set Objects
var workflowProvider = Builder.CreateInstance<WorkflowProvider>();
workflowProvider.UnitOfWork = unitOfWork;

// at this point...I can do my tests

As you can see...with SMALLER tests this isn't a problem. However, for larger tests that have more instances...it can get very "busy".

FOR EXAMPLE:
As such, lets look at a LARGER test...
See how I am having to plug-in the the UOW instance everywhere? I am hoping to avoid this.

// ARRANGE
var unitOfWork = Builder.CreateInstance<MeasurementContractsUnitOfWork>();

// Load Data
Builder.DefaultDataScenario.Load(unitOfWork);

// Set Objects
var workflowProvider = Builder.CreateInstance<WorkflowProvider>();
var builderATF = Builder.CreateInstance<AuthorizationToFlowDocumentDataSetBuilder>();
var providerATF = Builder.CreateInstance<AuthorizationToFlowDocumentProvider>();

workflowProvider.UnitOfWork = unitOfWork;
builderATF.UserManager.UnitOfWork = unitOfWork;
builderATF.WorkflowProvider = workflowProvider;
builderATF.UserMetaDataComponent.UnitOfWork = unitOfWork;
builderATF.UnitOfWork = unitOfWork;

providerATF.MeterProvider.UnitOfWork = unitOfWork;
providerATF.CommentingProvider.UnitOfWork = unitOfWork;
providerATF.DocumentParticipationProvider.UnitOfWork = unitOfWork;
providerATF.FavoritesManager.UnitOfWork = unitOfWork;
providerATF.UserManager.UnitOfWork = unitOfWork;
providerATF.UnitOfWork = unitOfWork;

QUESTION:
Is there a way to tell StructureMap to hand-back the populated Unit-of-Work (UOW) instance to all classes at runtime (after I have populated the UOW)?

Just to be clear...once I have populated the initial UOW instance...I want StructireMap to use that instance for all future CreateInstance calls


Solution

  • Turns out, all you have to do is use the INJECT method.

    [TestMethod]
    public void Experimental_UnitTest()
    {
        // STEP 1: Create a container within the scope of your individual UnitTest
        var container = IoC.Initialize();
        var unitOfWork = container.GetInstance<MeasurementContractsUnitOfWork>();
    
        // STEP 2: Load Your Data
        Builder.DefaultDataScenario.Load(unitOfWork);
    
        // STEP 3: "Inject" your instance
        container.Inject<MeasurementContractsUnitOfWork>(unitOfWork);
    
        // From here forward...all Instances created will get a copy of the populated UnitOfWork
        // This includes any PROPERTY objects that StructureMap creates within each instance too
        var builderRTF = container.GetInstance<RequestToFlowDocumentDataSetBuilder>();
        var builderATF = container.GetInstance<AuthorizationToFlowDocumentDataSetBuilder>();
    
    }
    

    For those that may want to "see" what is happening in the Load method:
    As you can see, you're loading-up the Unit of Work with test data...

    public void Load(MeasurementContractsUnitOfWork unitOfWork)
    {
        // Lookups
        Load_Area(unitOfWork);
        Load_State(unitOfWork);
        Load_County(unitOfWork);
    
        // Entities
        Load_Users(unitOfWork);
        
        // etc...
    }
    
    private void Load_Area(MeasurementContractsUnitOfWork unitOfWork)
    {
        var collection = new List<Area>();
    
        collection.Add(new Area { Id = 1, AreaName = "East Texas", CreateUserId = CREATED_BY_ID, CreateDate = DateTime.Now, UpdateUserId = CREATED_BY_ID, UpdateDate = DateTime.Now, IsActive = true });
        collection.Add(new Area { Id = 2, AreaName = "Intrastate", CreateUserId = CREATED_BY_ID, CreateDate = DateTime.Now, UpdateUserId = CREATED_BY_ID, UpdateDate = DateTime.Now, IsActive = true });
        collection.Add(new Area { Id = 3, AreaName = "Louisana", CreateUserId = CREATED_BY_ID, CreateDate = DateTime.Now, UpdateUserId = CREATED_BY_ID, UpdateDate = DateTime.Now, IsActive = true });
        collection.Add(new Area { Id = 4, AreaName = "Midcon", CreateUserId = CREATED_BY_ID, CreateDate = DateTime.Now, UpdateUserId = CREATED_BY_ID, UpdateDate = DateTime.Now, IsActive = true });
        collection.Add(new Area { Id = 5, AreaName = "Northeast", CreateUserId = CREATED_BY_ID, CreateDate = DateTime.Now, UpdateUserId = CREATED_BY_ID, UpdateDate = DateTime.Now, IsActive = true });
        collection.Add(new Area { Id = 6, AreaName = "North Texas", CreateUserId = CREATED_BY_ID, CreateDate = DateTime.Now, UpdateUserId = CREATED_BY_ID, UpdateDate = DateTime.Now, IsActive = true });
        collection.Add(new Area { Id = 7, AreaName = "South Texas", CreateUserId = CREATED_BY_ID, CreateDate = DateTime.Now, UpdateUserId = CREATED_BY_ID, UpdateDate = DateTime.Now, IsActive = true });
        collection.Add(new Area { Id = 8, AreaName = "West Texas", CreateUserId = CREATED_BY_ID, CreateDate = DateTime.Now, UpdateUserId = CREATED_BY_ID, UpdateDate = DateTime.Now, IsActive = true });
    
        unitOfWork.Area.CreateList(collection);
    }