Structure Map - Replace Interface with mock object at runtime - c#

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)

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);
}

Related

Nunit 3: Test a Controller that uses IHttpClientFactory as Constructor Parameter

Update 20221024: I have used Ruikai Feng's solution in order to use Mockoon with my tests. I realize this is not a correct approach from a unit testing approach and am working to change my approach.
Update 20221019: I have been using moq to mock out the IHttpClientFactory. The reason why I wanted to instantiate it was to call mock apis created in a tool called Mockoon which replicates apis. I have been so far unable to call these APIs likely because I have not yet properly mocked the ihttpclientfactory. I appreciate all the feedback as the solution is still ongoing at this time.
I am using a .NET 6 Web API controller with IHttpClientFactory to perform external API calls. As such, I have the following constructor:
public MyController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
This works because in my Program.cs I add an HTTP Client to my builder.Services.
In my tests, how do I instantiate/set up the httpClientFactory for the controller because I need it to instantiate my controller: var controller = new MyController(httpClientFactory); generates an error since there isn't any settings added.
I ran into a similar issue with configurations from appsettings.json and resolved with ConfigurationBuilder but there doesn't seem to be a similar one for IHttpClientFactory.
If you need any more information, please let me know. Thanks!
In order to be able to use a properly mocked IHttpClientFactory in your unit test you need to do the following steps:
Setup a DelegatingHandler mock
var mockHandler = new Mock<DelegatingHandler>();
mockHandler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", It.IsAny<HttpRequestMessage>(), It.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK))
.Verifiable();
mockHandler.As<IDisposable>().Setup(s => s.Dispose());
This sample mock will always return with 200 OK status code and without a response body
Tailor the setup for your needs
Create an HttpClient
var httpClient = new HttpClient(mockHandler.Object);
It creates an HttpClient instance and pass the above handler to it
Setup an IHttpClientFactory mock
var mockFactory = new Mock<IHttpClientFactory>(MockBehavior.Strict);
mockFactory
.Setup(factory => factory.CreateClient())
.Returns(httpClient)
.Verifiable();
It setups an IHttpClientFactory mock to return the above HttpClient for the CreateClient method call
If you use the IHttpClientFactory to create a named client then change the Setup to this .Setup(factory => factory.CreateClient(It.IsAny<string>()))
Use the mock objects for verification
mockFactory.Verify(factory => factory.CreateClient(), Times.Once);
mockHandler.Protected()
.Verify("SendAsync", Times.Once(), It.IsAny<HttpRequestMessage>(), It.IsAny<CancellationToken>());
I tried as below:
[TestFixture]
public class IndexActionTests
{
private HomeController controller;
[SetUp]
public void Setup()
{
var services = new ServiceCollection();
services.AddHttpClient();
var provider = services.BuildServiceProvider();
var httpclientfactory = provider.GetService<IHttpClientFactory>();
controller = new HomeController(httpclientfactory);
}
[Test]
public void Test1()
{
var result = controller.Index();
Assert.AreEqual(typeof(ViewResult),result.GetType());
}
}
Result:

Unit test the Get() Method using xUnit web api

Does any one know how to write a unit test (using xUnit) for the following Get() Method?
Get() method is in the controller and returns list of all Categories:
public class CategoryController : Controller
{
private MyContext x;
public CategoryController(MyContext y)
{
x = y;
}
[HttpGet]
public ActionResult<IEnumerable<Category>> Get()
{
return x.Categories.ToList();
}
}
If you are using EFCore as ORM, you can use InMemory database for unit testing.
There simple example:
[Fact]
public void TestGet()
{
_options = new DbContextOptionsBuilder<MyContext>()
.UseInMemoryDatabase(databaseName: "default")
.Options;
var context = new MyContext(_options);
context.EnsureSeed();
var controller = new CategoryController(context);
//Act
var results = controller.Get();
//Assert
Assert.NotNull(results);
Assert.True(results.Count > 0, "Expected to be greater than 0.");
}
Also you need implement EnsureSeed method. Example:
public static void EnsureSeed(this MyContext dataContext)
{
//Check if database is created, if not - create
dataContext.Database.EnsureCreated();
var category = new Category()
{
Id = 1
};
dataContext.Categories.Add(category);
dataContext.SaveChanges();
}
From what I've seen and read the best way to unit test a controller function is to create an instance of the server host from your test setup and make requests directly to your endpoint - this will allow you test the transport layer of your application like the API contract and Http protocols.
The following is an example implemented in .Net Core:
[Trait]
public class CategoryControllerTests : IClassFixture<WebApplicationFactory<Startup>>
{
// Startup - the entry point of most .net core project
private readonly WebApplicationFactory<Startup> _factory;
public CategoryControllerTests(WebApplicationFactory<Startup> factory)
{
// Any webhost config needed to run tests against the test
_factory = factory.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
// register any mock dependancies there - any dependencies in Startup.cs will hold unless overridden by a mock
services.AddScoped(x => new Mock() );
});
});
}
[Fact]
public async Task Get_ValidRequest_ReturnsData()
{
var client = _factory.CreateClient();
// Whatever routing protocol you use to define your endpoints
var url = "/category";
var response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsAsync<List<Category>>();
// Any asserts on your response
Assert.NotNull(content);
}
}
This is dependant on how you have setup the startup/initialisation of your project, it will allow you to test the project as though it were running in a production environment while letting you mock out any dependancies below the transport layer for a true unit test.
Note: the use of IClassFixture<WebApplicationFactory> - this will let you reuse an instance of WebApplicationFactory<Startup> for faster test execution; XUnit will inject this for you as part of the framework.

Unit Testing Umbraco 8 Composers

I'm fairly new to unit testing so go easy on me! I'm attempting to use a fairly simple Umbraco 8 project as a bit of a test bed. I'm currently stuck on trying to test a composer which registers a dependency and having a tough time figuring out how to test it.
The code will probably speak volumes so without further ado, here's the composer I'd like to test. As you can see, it simply registers a service coded against an interface:
using Papermoon.Umbraco.Utils.Services;
using Papermoon.Umbraco.Utils.Services.Interfaces;
using Umbraco.Core;
using Umbraco.Core.Composing;
namespace Papermoon.Umbraco.Aldus.Core.Composers
{
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
public class ServicesComposer : IUserComposer
{
public void Compose(Composition composition)
{
composition.Register<IPapermoonContentTypeContainerService, PapermoonContentTypeContainerService>();
}
}
}
After a lot of playing around, I found some code in the Umbraco source which means I can get a test passing based on the idea of registering a type. However, that is in no way in context of the ServicesComposer class. Hence, that wouldn't count against my code coverage and actually testing the class, rather than the ability to register something. Here's the code anyway:
using System;
using Moq;
using NUnit.Framework;
using Papermoon.Umbraco.Aldus.Core.Composers;
using Papermoon.Umbraco.Utils.Services;
using Papermoon.Umbraco.Utils.Services.Interfaces;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Composing.CompositionExtensions;
using Umbraco.Core.Logging;
namespace Papermoon.Umbraco.Aldus.Core.Tests.Composers
{
[TestFixture]
public class ServicesComposerTests
{
private ServicesComposer _servicesComposer;
[SetUp]
public void SetUp()
{
_servicesComposer = new ServicesComposer();
}
[Test]
public void Compose_WhenCalled_RegistersContentTypeContainerService()
{
Func<IFactory, IFactory> factoryFactory = null;
var mockedRegister = Mock.Of<IRegister>();
var mockedFactory = Mock.Of<IFactory>();
// the mocked register creates the mocked factory
Mock.Get(mockedRegister)
.Setup(x => x.CreateFactory())
.Returns(mockedFactory);
// the mocked register can register a factory factory
Mock.Get(mockedRegister)
.Setup(x => x.Register(It.IsAny<Func<IFactory, IFactory>>(), Lifetime.Singleton))
.Callback<Func<IFactory, IFactory>, Lifetime>((ff, lt) => factoryFactory = ff);
// the mocked factory can invoke the factory factory
Mock.Get(mockedFactory)
.Setup(x => x.GetInstance(typeof(IPapermoonContentTypeContainerService)))
.Returns(() => new Mock<IPapermoonContentTypeContainerService>().Object);
var logger = new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>());
var typeLoader = new TypeLoader(Mock.Of<IAppPolicyCache>(), "", logger);
var composition = new Composition(mockedRegister, typeLoader, logger, Mock.Of<IRuntimeState>());
var factory = composition.CreateFactory();
var resolved = factory.GetInstance<IPapermoonContentTypeContainerService>();
Assert.IsNotNull(resolved);
}
}
}
And the below code shows where I am at the moment, and is probably close to what the test should look like (if a little messy currently). I'm potentially way off the mark here so any help would go down a storm!
using System;
using Moq;
using NUnit.Framework;
using Papermoon.Umbraco.Aldus.Core.Composers;
using Papermoon.Umbraco.Utils.Services;
using Papermoon.Umbraco.Utils.Services.Interfaces;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Composing.CompositionExtensions;
using Umbraco.Core.Logging;
namespace Papermoon.Umbraco.Aldus.Core.Tests.Composers
{
[TestFixture]
public class ServicesComposerTests
{
private ServicesComposer _servicesComposer;
[SetUp]
public void SetUp()
{
_servicesComposer = new ServicesComposer();
Current.Factory = new Mock<IFactory>().Object;
}
[Test]
public void Compose_WhenCalled_RegistersContentTypeContainerService()
{
var mockedRegister = Mock.Of<IRegister>();
var logger = new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>());
var typeLoader = new TypeLoader(Mock.Of<IAppPolicyCache>(), "", logger);
var composition = new Composition(mockedRegister, typeLoader, logger, Mock.Of<IRuntimeState>());
_servicesComposer.Compose(composition);
var resolved = Current.Factory.GetInstance<IPapermoonContentTypeContainerService>();
Assert.IsNotNull(resolved);
}
}
}
I've also tried mocking up Composition to see if I could verify that the Register method has run but as this is a static method I get the following error:
Extension methods (here: RegisterExtensions.Register) may not be used in setup / verification expressions.
Here's the code that gets me to that error:
[Test]
public void Compose_WhenCalled_RegistersContentTypeContainerService()
{
Func<IFactory, IFactory> factoryFactory = null;
var mockedRegister = Mock.Of<IRegister>();
var mockedFactory = Mock.Of<IFactory>();
// the mocked register creates the mocked factory
Mock.Get(mockedRegister)
.Setup(x => x.CreateFactory())
.Returns(mockedFactory);
Mock.Get(mockedRegister)
.Setup(x => x.Register(It.IsAny<Func<IFactory, IFactory>>(), Lifetime.Singleton))
.Callback<Func<IFactory, IFactory>, Lifetime>((ff, lt) => factoryFactory = ff);
// the mocked factory can invoke the factory factory
Mock.Get(mockedFactory)
.Setup(x => x.GetInstance(typeof(IFactory)))
.Returns(() => factoryFactory?.Invoke(mockedFactory));
var logger = new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>());
var typeLoader = new TypeLoader(Mock.Of<IAppPolicyCache>(), "", logger);
var composition = new Mock<Composition>(mockedRegister, typeLoader, logger, new Mock<IRuntimeState>().Object);
composition.Verify(c => c.Register<IPapermoonContentTypeContainerService, PapermoonContentTypeContainerService>(It.IsAny<Lifetime>()));
}
Ultimately, I'm failing hard (and might have set my sights too high!), I'm not 100% sure on what to test here. My idea is that I want to test that the IPapermoonContentTypeContainerService is resolvable after _serviceComposer.Compose runs i.e. it's not null which ensures that it's been registered to the container. Potentially this isn't possible at which point, I wondered if testing that composition.Register<IPapermoonContentTypeContainerService, PapermoonContentTypeContainerService>(); was called was enough (as the actual registration part is third-party and therefore not to be tested). Or, am I barking up the wrong tree and this shouldn't actually be tested at all?
Thanks!
Ben
Register<TService, TImplementing> is a static extension method. You cannot mock extension methods, you'll need to look at the source for it & see what method it is calling under the hood.
For example, say I have a ILogger which exposes ILogger.Write(info level, string message) then I have an extension method:
public static void Info(this ILoggerlogger, string message) => logger.Write("Info", message);
When Info is called on a mocked instance of ILogger, the extension method is still called and the mocked ILogger.Write is called.
As you can see from the source code, the generic extension is calling another overload- that's the one you need to setup/verify:
composition.Verify(c => c.Register(typeof(IPapermoonContentTypeContainerService), typeof(PapermoonContentTypeContainerService), It.IsAny<Lifetime>()));
I'm not familiar with the service composers & suspect it's not possible; but rather than Compose(Composition composition), using IRegister (which Composition inherits from) would allow you to mock composition directly without having to mock it's dependencies...

Unit Test and IDistributedCache using azure redis

I have a working implementation of Azure Redis and .Net Core 2 using code very similar to what's described in this article
My question is, how do you instantiate an instance of the cache from a unit test class? I've looked through a number of resources and found nothing.
I need to be able to create an instance to instantiate a class such as
public CacheManager(IDataManager dataservices, IDistributedCache cache)
{
_cache = cache;
_dataservices = dataservices;
}
The code in startup.cs uses ConfigureServices
//Configure Redis Cache
var redisconnection = Configuration.GetConnectionString("Redis");
services.AddDistributedRedisCache(o => { o.Configuration = redisconnection; });
Maybe I need to add a package to the unit test project? How is this done?
I have used the Microsoft.Extensions.Caching.Distributed.MemoryDistributedCache class for unit testing. This is an in-memory implementation of IDistributedCache.
Here is a snippet of my unit testing code.
[TestMethod]
public void ExampleTestMethod()
{
var expectedData = new byte[] { 100, 200 };
var opts = Options.Create<MemoryDistributedCacheOptions>(new MemoryDistributedCacheOptions());
IDistributedCache cache1 = new MemoryDistributedCache(opts);
cache1.Set("key1", expectedData);
var cachedData = cache1.Get("key1");
Assert.AreEqual(expectedData, cachedData);
//Use the variable cache as an input to any class which expects IDistributedCache
}
In my example, I am on .NET Core 3.1 and the relevant NUGET packages are
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="3.1.4" />
You could just mock the interfaces to behave as needed for the isolated unit test.
public void Test_CacheManager() {
//Arrange
IDataManager dataservices = new Mock<IDataManager>();
IDistributedCache cache = new Mock<IDistributedCache>();
var subject = new CacheManager(dataservices.Object, cache.Object);
//Setup the mocks to behave as expected.
//Act
//...call the method under test
//Assert
//...assert the expected behavior
}
The above example uses Moq in order to demonstrate how to mock instances of the dependencies of the class under test.
Reference Moq Quickstart to get a better understanding of how to use the mocking library.
If you are connecting to an actual redis connection then this will no longer be a unit test but an integration test, which would require a completely different approach.
public void Test_CacheManager() {
//Arrange
IDataManager dataservices = new Mock<IDataManager>();
//Setup the mocks to behave as expected.
//Configure Redis Cache
var services = new ServiceCollection();
var redisconnection = "...";
services.AddDistributedRedisCache(o => { o.Configuration = redisconnection; });
var provider = services.BuildServiceProvider();
IDistributedCache cache = provider.GetService<IDistributedCache>();
var subject = new CacheManager(dataservices.Object, cache);
//Act
//...call the method under test
//Assert
//...assert the expected behavior
}
This how i managed to do that in .net core 2.0 and 3.1.
You need to use MemoryDistributedCache. And pass it through your service constructor. Your service in a real word uses IDistributedCache by depedency injection. MemoryDistributedCache also implements IDistributedCache.
var mockedCacheSettings = new Mock<IOptions<CacheSettings>>();
var options = new OptionsWrapper<MemoryDistributedCacheOptions>(new MemoryDistributedCacheOptions());
_memoryDistributedCache = new MemoryDistributedCache(options);
_distributedCacheService = new DistributedCacheService(_memoryDistributedCache, mockedCacheSettings.Object, NullLogger<DistributedCacheService>.Instance);
i needed DistributedCache for test a service so i wrote these code:
private IDistributedCache BuildDistributedCash()
{
var opt = Options.Create(new MemoryDistributedCacheOptions());
return new MemoryDistributedCache(opt);
}
[Fact]
public async Task CheckStatusTest()
{
var buildDistributedCash= BuildDistributedCash();
var authService = new AuthService(buildDistributedCash);
var userName = "test.z#gmail.com";
bool result = await authService.CheckStatus(userName);
Assert.True(result);
}

MVC Integration tests with Unity IoC

Am trying Unity IoC, after using constructor based DI.
Problem is trying to get integration tests working.
http://patrick.lioi.net/2013/06/20/streamlined-integration-tests/
"Running your integration tests should exercise as much of the real system as is reasonably possible"
Patrick above describes setting up an IoC inside the MVC Unit test project.. but I'm stuck as to how to implement
public class HomeController : Controller
{
readonly IWinterDb db;
// Unity knows that if IWinterDb interface is asked for, it will inject in a new WinterDb()
public HomeController(IWinterDb db)
{
this.db = db;
}
public ActionResult Index()
{
var stories = db.Query<Story>()
.OrderByDescending(s => s.Rating)
.Include(s => s.StoryType);
return View(stories);
}
Unit tests are fine, passing in a fake:
[TestMethod]
public void Index_GivenFake_ShouldReturn100Stories()
{
var db = new FakeWinterDb();
db.AddSet(TestData.Stories);
var controller = new HomeController(db);
var result = controller.Index() as ViewResult;
var model = result.Model as IEnumerable<Story>;
Assert.AreEqual(100, model.Count());
}
However I like integration tests which test the whole stack:
//Integration tests depend on the test data inserted in migrations
[TestClass]
public class HomeControllerTestsIntegration
{
[TestMethod]
public void Index_GivenNothing_ResultShouldNotBeNull()
{
var controller = new HomeController();
var result = controller.Index() as ViewResult;
Assert.IsNotNull(result);
}
Problem: This will not compile (as no parameterless constructor). And Unity is not being called to inject in the correct dependency for HomeController.
Unity wire up:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
container.RegisterType<IWinterDb, WinterDb>();
// for authentication
container.RegisterType<AccountController>(new InjectionConstructor());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
Edit1:
[TestMethod]
public void Index_GivenNothing_ResultShouldNotBeNull()
{
UnityConfig.RegisterComponents();
var controller = UnityConfig.container.Resolve<HomeController>();
var result = controller.Index() as ViewResult;
Assert.IsNotNull(result);
}
Making sure the singleton is there.
public static class UnityConfig
{
public static UnityContainer container;
public static void RegisterComponents()
{
container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
//container.RegisterType<IWinterDb, WinterDb>();
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMappings.FromMatchingInterface, // Convention of an I in front of interface name
WithName.Default
); // Default not a singleton in Unity
// for authentication
container.RegisterType<AccountController>(new InjectionConstructor());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
Exposing Unity to the test project
You need to resolve your controller via the container for Unity to resolve dependencies for you.
It may be as simple as replacing this:
var controller = new HomeController();
with this:
var controller = container.Resolve<HomeController>();
You will obviously need to expose your container to your test class. This is something you would not normally do when wiring up your production code.

Categories