在.NET Core Test Project中读取appsettings json值

问题描述 投票:28回答:7

我的Web应用程序需要从appsettings.json文件中读取Document DB键。我创建了一个带有键名的类,并在ConfigureaServices()中读取Config部分:

    public Startup(IHostingEnvironment env) {
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddEnvironmentVariables();

        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; }

    public void ConfigureServices(IServiceCollection services) {
        services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
        services.AddSession();
        Helpers.GetConfigurationSettings(services, Configuration);
        DIBuilder.AddDependency(services, Configuration);
    }

我正在寻找在Test项目中读取Key值的方法。

unit-testing asp.net-core appsettings
7个回答
40
投票

这是基于博客文章Using Configuration files in .NET Core Unit Test Projects(为.NET Core 1.0编写)。

  1. 在Integration测试项目根目录中创建(或复制)appsettings.test.json,并在属性中将“Build Action”指定为Content,将“如果更新则复制”指定到Output Directory。请注意,最好使文件名(例如appsettings.test.json)与普通的appsettings.json不同,因为如果使用相同的名称,主项目中的文件可能会覆盖测试项目中的文件。
  2. 如果尚未包含JSON配置文件NuGet包(Microsoft.Extensions.Configuration.Json),请将其包含在内。
  3. 在测试项目中创建一个方法, public static IConfiguration InitConfiguration() { var config = new ConfigurationBuilder() .AddJsonFile("appsettings.test.json") .Build(); return config; }
  4. 像往常一样使用配置 var config = InitConfiguration(); var clientId = config["CLIENT_ID"]

顺便说一下:如Integration test with IOptions<> in .NET Core中所述,您也可能有兴趣将配置读入IOptions类:

var options = config.Get<MySettings>();

3
投票

老实说,如果你是一个单元测试应用程序,你应该尝试从所有依赖项中隔离你正在测试的类,比如调用其他类,访问文件系统,数据库,网络等。除非你正在进行集成测试或功能测试。

话虽如此,要对应用程序进行单元测试,您可能希望从appsettings.json文件中模拟这些值,然后测试您的逻辑。

所以你的appsettings.json看起来像这样。

"DocumentDb": {
    "Key": "key1" 
} 

然后创建一个设置类。

public class DocumentDbSettings
{
    public string Key { get; set; }
}

然后在ConfigureServices()方法中注册它。

services.Configure<DocumentDbSettings>(Configuration.GetSection("DocumentDb"));

然后例如您的控制器/类可能看起来像这样。

// ...
private readonly DocumentDbSettings _settings;

public HomeController(IOptions<DocumentDbSettings> settings)
{
    _settings = settings.Value;
}
// ...
public string TestMe()
{
    return $"processed_{_settings.Key}";
}

然后在您的测试项目中,您可以创建此类单元测试类。

public class HomeControllerTests
{
    [Fact]
    public void TestMe_KeyShouldBeEqual_WhenKeyIsKey1()
    {
        // Arrange
        const string expectedValue = "processed_key1";
        var configMock = Substitute.For<IOptions<DocumentDbSettings>>();
        configMock.Value.Returns(new DocumentDbSettings
        {
            Key = "key1" // Mocking the value from your config
        });

        var c = new HomeController(configMock);

        // Act
        var result = c.TestMe();

        // Assert
        Assert.Equal(expectedValue, result);
    }
}

我使用NSubstitute v2.0.0-rc进行模拟。


2
投票

在您测试项目的project.json中,添加以下依赖项:

"dependencies": {
  "xunit": "2.2.0-beta2-build3300",
  "Microsoft.AspNetCore.TestHost": "1.0.0",
  "dotnet-test-xunit": "2.2.0-preview2-build1029",
  "BancoSentencas": "1.0.0-*"
},

BancoSentencas是我想测试的项目。其他软件包来自xUnit和TestHost,它们将成为我们的内存服务器。

还包括appsettings.json的此构建选项:

"buildOptions": {
  "copyToOutput": {
    "include": [ "appsettings.Development.json" ]
  }
}

在我的测试项目中,我有以下测试类:

  public class ClasseControllerTeste : IClassFixture<TestServerFixture> {

    public ClasseControllerTeste(TestServerFixture fixture) {
      Fixture = fixture;
    }

    protected TestServerFixture Fixture { get; private set; }


    [Fact]
    public async void TestarRecuperarClassePorId() {
      using(var client = Fixture.Client) {
        var request = await Fixture.MyHttpRequestMessage(HttpMethod.Get, "/api/classe/1436");
        var response = await client.SendAsync(request);
        string obj = await response.Content.ReadAsStringAsync();
        ClasseModel classe = JsonConvert.DeserializeObject<ClasseModel>(obj);
        Assert.NotNull(classe);
        Assert.Equal(1436, classe.Id);
      }
    }
  }

我还有TestServerFixture类,它将配置内存服务器:

  public class TestServerFixture : IDisposable {
    private TestServer testServer;
    protected TestServer TestServer {
      get {
        if (testServer == null)
          testServer = new TestServer(new WebHostBuilder().UseEnvironment("Development").UseStartup<Startup>());
        return testServer;
      }
    }

    protected SetCookieHeaderValue Cookie { get; set; }

    public HttpClient Client {
      get {
        return TestServer.CreateClient();
      }
    }

    public async Task<HttpRequestMessage> MyHttpRequestMessage(HttpMethod method, string requestUri) {      
      ...
      login stuff...
      ...
      Cookie = SetCookieHeaderValue.Parse(response.Headers.GetValues("Set-Cookie").First());

      var request = new HttpRequestMessage(method, requestUri);

      request.Headers.Add("Cookie", new CookieHeaderValue(Cookie.Name, Cookie.Value).ToString());
      request.Headers.Accept.ParseAdd("text/xml");
      request.Headers.AcceptCharset.ParseAdd("utf-8");
      return request;
    }

    public void Dispose() {
      if (testServer != null) {
        testServer.Dispose();
        testServer = null;
      }
    }
  }

这就是我测试我的项目的方式。我使用主项目中的Startup.cs,并在我的测试项目中创建appsettings.json的副本(appsettings.Development.json)


2
投票

Suderson的解决方案适用于我,修改如下:

        var builder = new ConfigurationBuilder()
             .SetBasePath(Directory.GetCurrentDirectory())
             .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
             .AddEnvironmentVariables();

        IConfiguration config = builder.Build();

        //Now, You can use config.GetSection(key) to get the config entries

1
投票

appSettings.json复制到Test项目根目录,并将其属性标记为Content and Copy if new。

var builder = new ConfigurationBuilder()
  .SetBasePath(Directory.GetCurrentDirectory())
  .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
  .AddEnvironmentVariables();
ConfigurationManager.Configuration = builder.Build();

ConfigurationManager是一个类,它有一个静态属性Configuration。这样整个应用程序就可以像ConfigurationManager.Configuration[<key>]一样访问它


0
投票

对于ASP.NET Core 2.x项目,将appsettings.json文件自动复制到build dir:

<Project Sdk="Microsoft.NET.Sdk">
  <ItemGroup>
    <None Include="..\MyProj\appsettings.json" CopyToOutputDirectory="PreserveNewest" />
  </ItemGroup>
</Project>

0
投票

如果您正在使用WebApplicationFactory to create a test server for integration tests并且您已经有办法获得服务器端控制器中的配置值(您可能会这样做!),那么您可以重新使用它(并获取您需要的任何其他注入项目)您的集成测试如下:

// Your test fixtures would be subclasses of this
public class IntegrationTestBase : IDisposable
{
    private readonly WebApplicationFactory<Startup> _factory;
    protected readonly HttpClient _client;

    // The same config class which would be injected into your server-side controllers
    protected readonly IMyConfigService _myConfigService;

    // Constructor (called by subclasses)
    protected IntegrationTestBase()
    {
        // this can refer to the actual live Startup class!
        _factory = new WebApplicationFactory<Startup>();
        _client = _factory.CreateClient();

        // fetch some useful objects from the injection service
        _myConfigService = (IMyConfigService)_factory.Server.Host.Services.GetService(typeof(IMyConfigService));
    }

    public virtual void Dispose()
    {
        _client.Dispose();
        _factory.Dispose();
    }
}

请注意,在这种情况下,您不需要复制appsettings.json,您将自动使用(测试)服务器正在使用的相同appsettings.json

© www.soinside.com 2019 - 2024. All rights reserved.