web-dev-qa-db-fra.com

Lecture des valeurs japp appsettings dans le projet de test .NET Core

Mon application Web doit lire les clés de la base de données de documents à partir du fichier appsettings.json. J'ai créé une classe avec les noms de clé et lu la section Config dans ConfigureaServices() comme:

    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);
    }

Je cherche les moyens de lire les valeurs Key dans le projet Test.

30
S.Siva

Ceci est basé sur le blog tilisation des fichiers de configuration dans les projets de test .NET Core Unit (écrit pour .NET Core 1.0) .

  1. Créez (ou copiez) le fichier appsettings.test.json dans le répertoire racine du projet de test d'intégration et dans les propriétés, spécifiez "Action de génération" comme contenu et "Copier, le cas échéant" dans le répertoire de sortie. Notez qu’il est préférable d’avoir un nom de fichier (par exemple, appsettings.test.json) différent de la normale appsettings.json, car il est possible qu'un fichier du projet principal remplace le fichier du projet test si le même nom est utilisé.

  2. Incluez le package NuGet du fichier de configuration JSON (Microsoft.Extensions.Configuration.Json) s'il n'est pas encore inclus.

  3. Dans le projet de test, créez une méthode,

    public static IConfiguration InitConfiguration()
            {
                var config = new ConfigurationBuilder()
                    .AddJsonFile("appsettings.test.json")
                    .Build();
                    return config;
            }
    
  4. Utilisez la configuration comme d'habitude

    var config = InitConfiguration();
    var clientId = config["CLIENT_ID"]
    

BTW: Vous pouvez également être intéressé par la lecture de la configuration dans la classe IOptions comme décrit dans Test d'intégration avec IOptions <> dans .NET Core:

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

Honnêtement, si vous testez une unité comme une application, vous devriez essayer d'isoler la classe que vous testez de toutes les dépendances, comme appeler d'autres classes, accéder au système de fichiers. , base de données, réseau, etc. Sauf si vous effectuez des tests d'intégration ou des tests de fonctionnement.

Cela dit, pour tester un peu l'application, vous voudrez probablement simuler ces valeurs à partir de votre fichier appsettings.json et simplement tester votre logique.

Ainsi, votre appsettings.json Ressemblerait à ceci.

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

Créez ensuite une classe de paramètres.

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

Puis enregistrez-le dans la méthode ConfigureServices().

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

Ensuite, par exemple, votre contrôleur/classe pourrait ressembler à ceci.

// ...
private readonly DocumentDbSettings _settings;

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

Ensuite, dans votre projet de tests, vous pouvez créer une telle classe de tests unitaires.

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);
    }
}

J'ai utilisé NSubstitute v2.0.0-rc pour me moquer.

3
Ignas

Dans le project.json de votre projet test, ajoutez les dépendances suivantes:

"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 est le projet que je veux tester. Les autres paquets proviennent de xUnit et de TestHost qui sera notre serveur en mémoire.

Incluez également cette option de construction pour le fichier appsettings.json:

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

Dans mon projet de test, j'ai la classe de test suivante:

  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);
      }
    }
  }

Et j'ai aussi la classe TestServerFixture qui va configurer le serveur en mémoire:

  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;
      }
    }
  }

C'est comme ça que je teste mon projet. J'utilise le fichier Startup.cs du projet principal et j'en crée une copie à partir du fichier appsettings.json de mon projet test (appsettings.Development.json).

2
Fabricio Koch

La solution de Suderson a fonctionné pour moi lorsqu'elle a été modifiée comme suit:

        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
2
Bob

Copiez le appSettings.json dans le répertoire racine de votre projet test et marquez sa propriété comme Conten et Copier si plus récent.

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

ConfigurationManager est une classe et a une propriété statique Configuration. De cette façon, toute l'application peut simplement y accéder en tant que ConfigurationManager.Configuration[<key>]

1

Si vous utilisez WebApplicationFactorypour créer un serveur de test pour les tests d'intégration et que vous disposez déjà d'un moyen d'obtenir des valeurs de configuration dans vos contrôleurs côté serveur (vous le faites probablement!), Alors vous pouvez simplement réutiliser ceci (et obtenir tout autre élément injecté dont vous avez besoin) dans vos tests d'intégration, comme suit:

// 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();
    }
}

Notez qu'il n'est pas nécessaire de copier par dessus appsettings.json dans ce cas, vous utilisez automatiquement le même appsettings.json que le serveur (test) utilise.

0
Mike Beaton

Pour les projets ASP.NET Core 2.x, copiez le fichier appsettings.json fichier dans le répertoire de construction automatiquement:

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