os blue os blue - 2 months ago 21
C# Question

Structure Map - Replace Interface with mock object at runtime

I am doing some integration tests for my OWIN based Web API. I am using structure map as DI container. In one of the cases, I need to mock out an API call ( can't include it as part of the test).

How would I go about doing this using Structure Map? I have done it using SimpleInjector but the code base I am working on is using Structure Map and I can't figure out how I would do this.

Solution with SimpleInjector:

Startup.cs

public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
app.UseWebApi(WebApiConfig.Register(config));

// Register IOC containers
IOCConfig.RegisterServices(config);
}


ICOCConfig:

public static Container Container { get; set; }
public static void RegisterServices(HttpConfiguration config)
{
Container = new Container();

// Register
config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(Container);
}


And in my Integration test, I mock out the interface that calls the other API.

private TestServer testServer;
private Mock<IShopApiHelper> apiHelper;

[TestInitialize]
public void Intitialize()
{
testServer= TestServer.Create<Startup>();
apiHelper= new Mock<IShopApiHelper>();
}

[TestMethod]
public async Task Create_Test()
{
//Arrange
apiHelper.Setup(x => x.CreateClientAsync())
.Returns(Task.FromResult(true);

IOCConfig.Container.Options.AllowOverridingRegistrations = true;
IOCConfig.Container.Register<IShopApiHelper>(() => apiHelper.Object, Lifestyle.Transient);

//Act
var response = await testServer.HttpClient.PostAsJsonAsync("/api/clients", CreateObject());

//Assert
Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);
}


I found this in the structure-map documentation but it doesn't allow me to inject a mock object in there (only types).

How I can inject a mock version of IShopApiHelper (Mock) when running my integration tests? (I am using the Moq library for mocking)

Answer Source

Assuming the same API structure as in the original example you can do basically the same thing as demonstrated in the linked documentation.

[TestMethod]
public async Task Create_Test() {
      //Arrange
      apiHelper.Setup(x => x.CreateClientAsync())
               .Returns(Task.FromResult(true);

       // Use the Inject method that's just syntactical
      // sugar for replacing the default of one type at a time    
      IOCConfig.Container.Inject<IShopApiHelper>(() => apiHelper.Object);

      //Act
      var response = await testServer.HttpClient.PostAsJsonAsync("/api/clients", CreateObject());

      //Assert
      Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);
}