-
Notifications
You must be signed in to change notification settings - Fork 0
Testing
Arsenty Politov edited this page Mar 15, 2019
·
1 revision
Contains various extensions and mocks that can be used to emulate application environment in unit tests.
- DevGuild.AspNetCore.Testing
- DevGuild.AspNetCore.Testing.Data
- DevGuild.AspNetCore.Testing.Hosting
- DevGuild.AspNetCore.Testing.Identity
- DevGuild.AspNetCore.Testing.Mvc
- DevGuild.AspNetCore.Testing.Storage
- Install necessary packages into test project (they shouldn't be present in main project).
- Add class TestEnvironmentConfiguration that implements interface IMockConfiguration provided by one of the packages.
- Build an in-memory configuration, that can be used to configure services by adding method like this:
public virtual IConfiguration BuildConfiguration()
{
var configurationData = new Dictionary<String, String>
{
{ "ConnectionStrings:DefaultConnection", $"InMemory-{Guid.NewGuid():D}" },
{ "Bundling:Enabled", "false" },
{ "Storage:Images:Type", "InMemory" },
{ "Storage:Images:BaseUrl", "/images" },
{ "Storage:Files:Type", "InMemory" },
{ "Storage:Files:BaseUrl", "/files" },
{ "Mail:System:Type", "None" },
{ "Mail:System:Sender", "[email protected]" },
{ "Mail:System:BlindCopy", "[email protected]" },
{ "Mail:System:DebugMode", "true" },
{ "Sms:System:Type", "None" },
{ "Sms:System:SenderName", "DevGuild" }
};
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddInMemoryCollection(configurationData);
return configurationBuilder.Build();
}
- Implement required method ConfigureServices to mirror ConfigureServices from Startup class of main project.
- Some services can be skipped.
- Mock IHostingEnvironment by using services.MockHostingEnvironment extension:
- Instead of all storage providers, use AddInMemoryProvider to register InMemory provider.
- Instead of Sql Server or another database, use UseInMemoryDatabase to register InMemory database.
- Instead of using AddStateServices* extension to add identity services, use MockStateServices*.
- Don't use any live Email or SMS providers. Built-in None provider should be enough for testing.
- Use MockUrlHelper to register IUrlHelper service mock.
- Most of the domain services can be left as is.
- Add TestEnvironment class that inherits from MockEnvironmentBase with following code:
public class TestEnvironment : MockEnvironmentBase
{
public static IMockEnvironment Create()
{
return MockEnvironment.Create<TestEnvironment>(new TestEnvironmentConfiguration());
}
}
- Create a testing environment by using TestEnvironment.Create method.
- Store created environment in test class instance field.
- If necessary - seed the data required for testing using environment.SeedAsync extension.
private IMockEnvironment environment;
[SetUp]
public async Task Setup()
{
this.environment = TestEnvironment.Create();
await this.environment.SeedAsync(async seeder =>
{
await seeder.SeedRolesAsync<DbContext, Role, Guid>("Administrator");
});
}
- If necessary - seed the data required for a specific test using environment.SeedAsync extension.
- Use environment.BeginRequest method to initialize request scope.
- Wrap it in using statement to automatically dispose request scope.
- Perform the testing.
- Use request.SignInAsync extension to emulate sign in as specific user (user needs to be seeded beforehand).
- Use request.GetService method to get registered service.
- Use request.CreateInstanceOf method to create a new instance of specified class with necessary dependencies injected (can be used to create controller instances).
[Test]
public async Task HomeIndex()
{
await this.environment.SeedAsync(async seeder =>
{
await seeder.SeedUserAsync<DbContext, ApplicationUser, Role, Guid>("admin", null, "Password123!", "Administrator");
});
using (var request = this.environment.BeginRequest())
{
await request.SignInAsync("admin");
var controller = request.CreateInstanceOf<HomeController>();
var result = await controller.Index();
Assert.That(result, Is.InstanceOf<ViewResult>());
}
}
- Dispose instance of testing environment.
[TearDown]
public void TearDown()
{
this.environment.Dispose();
}