Introduction
I'm writing unit tests for an extension method I wrote. Its only purpose it is to wrap startup logic which extends ViewLocationExpanders list by an instance implementating IViewLocationExpander. ViewLocationExpanders is a property of RazorViewEngineOptions, which can be configured in application startup in ConfigureServices() method. I'm using XUnit 2.4.1.
Usage
Instead of:
services.Configure<RazorViewEngineOptions>(options =>
{
options.ViewLocationExpanders.Add(new ViewLocationExpander());
});
I can use:
services.AddViewLocationExpander(new ViewLocationExpander());
ViewLocationExpander
public class ViewLocationExpander : IViewLocationExpander
{
public IEnumerable<string> ExpandViewLocations(
ViewLocationExpanderContext context,
IEnumerable<string> viewLocations)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (viewLocations == null)
{
throw new ArgumentNullException(nameof(viewLocations));
}
/*
* Note:
* {0} = action name
* {1} = controller name
* {2} = area name
*/
var newViewLocations = new string[]
{
// Example: '/Views/Home/_Partials/FooBar.cshtml'
"/Views/{1}/_Partials/{0}.cshtml",
};
// Add new locations *AFTER* MVC default locations.
return viewLocations.Union(newViewLocations);
}
public void PopulateValues(ViewLocationExpanderContext context)
{
context.Values["customviewlocation"] = nameof(ViewLocationExpander);
}
}
Extension method
public static IServiceCollection AddViewLocationExpander(
this IServiceCollection services,
IViewLocationExpander viewLocationExpander)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
if (viewLocationExpander == null)
{
throw new ArgumentNullException(nameof(viewLocationExpander));
}
return services.Configure<RazorViewEngineOptions>(options =>
{
options.ViewLocationExpanders.Add(viewLocationExpander);
});
}
Unit tests
[Fact]
public void ExtensionMethodAddsNewViewLocationExpander()
{
// Arrange
var services = new ServiceCollection();
services.AddMvc();
// These two are required to active the RazorViewEngineOptions.
services.AddSingleton<IHostingEnvironment, HostingEnvironment>();
services.AddSingleton<ILoggerFactory, LoggerFactory>();
// Act
var serviceProvider = services.BuildServiceProvider();
var oldOptions = serviceProvider.GetRequiredService<IOptions<RazorViewEngineOptions>>().Value;
services.AddViewLocationExpander(new ViewLocationExpander());
serviceProvider = services.BuildServiceProvider();
var newOptions = serviceProvider.GetRequiredService<IOptions<RazorViewEngineOptions>>().Value;
// Assert
Assert.True(newOptions.ViewLocationExpanders.Count > oldOptions.ViewLocationExpanders.Count);
}
Questions
- Am I going beyond the scope of what unit testing should include? I'm afraid that my code is actually testing the basic functions of generic collections and/or aspects of ASP.NET Core.
- If my concern above is true, that should I write unit tests to this at all? How should it work?