Set the IHostingEnvironment in unit test
Asked Answered
T

4

36

I am currently upgrading a project from .NET Core RC1 to the new RTM 1.0 version. In RC1, there was a IApplicationEnvironment which was replaced with IHostingEnvironment in version 1.0

In RC1 I could do this

public class MyClass
{
    protected static IApplicationEnvironment ApplicationEnvironment { get;private set; }

    public MyClass()
    {
        ApplicationEnvironment = PlatformServices.Default.Application;
    }
}

Does anyone know how to achieve this in v1.0?

public class MyClass
{
    protected static IHostingEnvironment HostingEnvironment { get;private set; }

    public MyClass()
    {
        HostingEnvironment = ???????????;
    }
}
Thera answered 1/7, 2016 at 0:59 Comment(1)
You could just mock it in the unit test by implementing the interface.Quadrivial
G
38

You can mock the IHostEnvironment using a mocking framework if needed or create a fake version by implementing the interface.

Give a class like this...

public class MyClass {
    protected IHostingEnvironment HostingEnvironment { get;private set; }

    public MyClass(IHostingEnvironment host) {
        HostingEnvironment = host;
    }
}

You can setup a unit test example using Moq...

public void TestMyClass() {
    //Arrange
    var mockEnvironment = new Mock<IHostingEnvironment>();
    //...Setup the mock as needed
    mockEnvironment
        .Setup(m => m.EnvironmentName)
        .Returns("Hosting:UnitTestEnvironment");
    //...other setup for mocked IHostingEnvironment...

    //create your SUT and pass dependencies
    var sut = new MyClass(mockEnvironment.Object);

    //Act
    //...call you SUT

    //Assert
    //...assert expectations
}
Gonophore answered 12/7, 2016 at 2:39 Comment(3)
In such way you can't setup extension method like IsDevelopment();Meister
@Meister Why do you need to setup it? If you setup the "EnvironmentName" of the mock object to "Development" then the 'IsDevelopment' extension method will return 'true'. At least in my case, that's all I need.Oversell
Super clean, worked like a charmLifeblood
C
23

Using Microsoft.Extensions.Hosting (which is one of the included packages in ASP.NET Core), you can use:

IHostEnvironment env = 
    new HostingEnvironment { EnvironmentName = Environments.Development };
Counterpart answered 17/7, 2020 at 7:12 Comment(4)
Although useful, keep in mind it's an internal API: Microsoft.Extensions.Hosting.Internal.HostingEnvironment.Papacy
It's an 'internal' API, not an internal one :)Counterpart
LOL true, typo. :) Though it's still an "internal API" and cannot be trusted. Amazing how much stuff is hard to test because of those internals.Papacy
If you are unit testing; This method allows you to modify new variables with ease.Zestful
R
7

In general, as IHostingEnvironment is just an interface, you can simply mock it to return whatever you want.

If you are using TestServer in your tests, the best way to mock is to use WebHostBuilder.Configure method. Something like this:

var testHostingEnvironment = new MockHostingEnvironment(); 
var builder = new WebHostBuilder()
            .Configure(app => { })
            .ConfigureServices(services =>
            {
                services.TryAddSingleton<IHostingEnvironment>(testHostingEnvironment);
            });
var server = new TestServer(builder);
Rhaetian answered 1/7, 2016 at 9:8 Comment(2)
I don't want to use the TestServer class. That's more for integration testing I believe. I don't need to spin up a complete instance of the app. I just want to test a particular class. What I have is a Test base class that used ApplicationEnvironment in RC1, but I cannot seem to replace it easily in 1.0Thera
So why you don't like to just mock it? HostingEnvironment = < your mock implementation of IHostingEnvironment>Rhaetian
M
0

This is how we do it in our tests:

     var serviceProvider =  new ServiceCollection()
        .AddScoped<IHostingEnvironment, MockHostingEnvironment>()
        .AddScoped<IAccessPointService, AccessPointService>()
          .BuildServiceProvider();

The definition of MockHosting, you can change the implementation for something to fit your needs:

 public class MockHostingEnvironment : IHostingEnvironment
{
    public string EnvironmentName { get => return "Testing"; set => throw new NotImplementedException(); }
    public string ApplicationName { get => "My App"; set => throw new NotImplementedException(); }
    public string ContentRootPath { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    public IFileProvider ContentRootFileProvider { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
}

Finally, we just ask the service provider an instance of the Class needing the DI:

    var accessPointService = serviceProvider.GetService<IAccessPointService>();     
Mayda answered 27/10, 2021 at 23:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.