Using IHostingEnvironment in a test project


5 years ago -  
ASP.NET CorexUnit.NET Core

Assume that you have a service which accepts IHostingEnvironment as its dependency:

public class MyService
{
    private readonly IHostingEnvironment hostingEnv;

    public MyService(IHostingEnvironment hostingEnv)
    {
        this.hostingEnv = hostingEnv;
    }

    public Task<IEnumerable<Post>> GetPosts()
    {
        var fileInfo = hostingEnv.ContentRootFileProvider.GetFileInfo("posts.json");
        var file = File.ReadAllText(file.PhysicalPath);
        var deserializeObject = JsonConvert.DeserializeObject<IEnumerable<Post>>(file);
        return Task.FromResult(deserializeObject);
    }
}

Now we wan to be able to load that JSON file inside a test project in order to test the service. First of all, we need to make sure we have these packages installed on the test project:

<ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.2.0" />
    <PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="2.2.0" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
    <PackageReference Include="xunit" Version="2.4.0" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>

We also need to modify the csproj file to copy the JSON file to the build output:

<ItemGroup>
    <None Update="data.json">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
</ItemGroup>

Then we need a base class to configure the built-in DI container and register IHostingEnvironment:

namespace GreatSpot.Tests
{
    public class BaseTest
    {
        public static IServiceProvider Services { get; private set; }
        public BaseTest()
        {
            var serviceCollection = new ServiceCollection();
            serviceCollection.AddSingleton<IHostingEnvironment>(new HostingEnvironment
            {
                ContentRootFileProvider = new PhysicalFileProvider(Environment.CurrentDirectory)
            });
            Services = serviceCollection.BuildServiceProvider();
        }
    }
}

Now we can use the registred service in our test methods:

public class PostTests : BaseTest
{
    [Fact]
    public async Task Get_All_Posts()
    {
        var hostingEnvironment = Services.GetService<IHostingEnvironment>();

        var myService = new MyService(hostingEnvironment);
        var data = await myService.GetPosts();
        Assert.Equal(10, data.Count);
    }
}