Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recommended approach for automated testing of both code paths in ASP.NET Core? #19

Closed
antmdvs opened this issue Nov 5, 2019 · 2 comments

Comments

@antmdvs
Copy link
Contributor

antmdvs commented Nov 5, 2019

Hi! I appreciate the work being done here.

One thing I haven't been able to find in the docs are examples of automated tests showing how to exercise both code paths (with a given feature both on & off).

Would the suggestion be to stub IFeatureManager or is there a more idiomatic approach the team recommends?

To illustrate what I'm asking with code, this is what I've got working so far:
(based on https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-3.0#inject-mock-services)

[Fact]
public async Task FeatureA_ShouldBePresent_WhenConfiguredOn()
{
	// Arrange
	var client = _factory
		.WithWebHostBuilder(builder =>
		{
			builder.ConfigureServices(services =>
			{
				services.AddScoped<IFeatureManager, StubFeatureManagerWithFeatureAOn>();
			});
		})
		.CreateClient();

	// Act
	var response = await client.GetAsync("/Home/FeatureA");

	// Assert
	response.EnsureSuccessStatusCode(); // Status Code 200-299
	Assert.Equal("text/html; charset=utf-8",
			response.Content.Headers.ContentType.ToString());
}

[Fact]
public async Task FeatureA_ShouldNotBePresent_WhenConfiguredOff()
{
	// Arrange
	var client = _factory
		.WithWebHostBuilder(builder =>
		{
			builder.ConfigureServices(services =>
			{
				services.AddScoped<IFeatureManager, StubFeatureManagerWithFeatureAOff>();
			});
		})
		.CreateClient();

	// Act
	var response = await client.GetAsync("/Home/FeatureA");

	// Assert
	Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}

The salient lines in this snippet are:

services.AddScoped<IFeatureManager, StubFeatureManagerWithFeatureAOn>();
services.AddScoped<IFeatureManager, StubFeatureManagerWithFeatureAOff>();

The actual stub code is not shown (could use hand-rolled or Moq, etc.).

Does the team have a different recommendation for toggling a feature on a per-test basis?

@jimmyca15
Copy link
Member

If you are just testing the application's ability to react on feature manager evaluations then I would say that stubbing the feature manager is a proper way to accomplish this. You could create a test implementation of IFeatureManager which contains the desired state of all features as a dictionary.

I wouldn't say that there is a one solution fits all approach. Some tests may require a more dynamic approach and in that case you could directly interact with a TestFilter as shown in this code snippet:

testFeatureFilter.Callback = (evaluationContext) =>

@antmdvs
Copy link
Contributor Author

antmdvs commented Nov 20, 2019

Thanks, Jimmy.

Just to clarify, the reason behind my question was based on this excerpt from Pete Hodgson's article on Martin Fowler's blog:

We can create a new toggle router based on some default configuration - perhaps read in from a config file - but we can also dynamically toggle a feature on or off. This allows automated tests to verify both sides of a toggled feature:

Also,

You could create a test implementation of IFeatureManager which contains the desired state of all features as a dictionary.

Good point. I realize the stubbing approach in #19 (comment) would degrade in maintainability as the # of features grows. I hadn't fully thought that threw so I'll definitely take this into consideration.

@antmdvs antmdvs closed this as completed Nov 20, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants