Ich habe das Gefühl, dass mir hier etwas wirklich Offensichtliches fehlt. Ich habe Klassen, in denen Optionen mithilfe des .Net Core IOptions-Musters (?) Eingefügt werden müssen. Wenn ich zum Unit-Test dieser Klasse gehe, möchte ich verschiedene Versionen der Optionen verspotten, um die Funktionalität der Klasse zu überprüfen. Weiß jemand, wie man IOptions außerhalb der Startup-Klasse korrekt verspottet / instanziiert / auffüllt?
Hier sind einige Beispiele der Klassen, mit denen ich arbeite:
Einstellungs- / Optionsmodell
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace OptionsSample.Models
{
public class SampleOptions
{
public string FirstSetting { get; set; }
public int SecondSetting { get; set; }
}
}
Zu testende Klasse, die die Einstellungen verwendet:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using OptionsSample.Models
using System.Net.Http;
using Microsoft.Extensions.Options;
using System.IO;
using Microsoft.AspNetCore.Http;
using System.Xml.Linq;
using Newtonsoft.Json;
using System.Dynamic;
using Microsoft.Extensions.Logging;
namespace OptionsSample.Repositories
{
public class SampleRepo : ISampleRepo
{
private SampleOptions _options;
private ILogger<AzureStorageQueuePassthru> _logger;
public SampleRepo(IOptions<SampleOptions> options)
{
_options = options.Value;
}
public async Task Get()
{
}
}
}
Unit Test in einer anderen Baugruppe als die anderen Klassen:
using OptionsSample.Repositories;
using OptionsSample.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
namespace OptionsSample.Repositories.Tests
{
public class SampleRepoTests
{
private IOptions<SampleOptions> _options;
private SampleRepo _sampleRepo;
public SampleRepoTests()
{
//Not sure how to populate IOptions<SampleOptions> here
_options = options;
_sampleRepo = new SampleRepo(_options);
}
}
}
IOptions<T>
Sie müssen sich nur verspottenValue
, um die gewünschte Klasse zurückzugebenAntworten:
Sie müssen ein
IOptions<SampleOptions>
Objekt manuell erstellen und füllen . Sie können dies über dieMicrosoft.Extensions.Options.Options
Hilfsklasse tun . Beispielsweise:Sie können das ein wenig vereinfachen, um:
Offensichtlich ist dies nicht sehr nützlich. Sie müssen tatsächlich ein SampleOptions-Objekt erstellen, füllen und an die Create-Methode übergeben.
quelle
new OptionsWrapper<SampleOptions>(new SampleOptions());
überall zu schreibenWenn Sie das Mocking Framework verwenden möchten, wie im Kommentar unter @TSeng angegeben, müssen Sie der Datei project.json die folgende Abhängigkeit hinzufügen.
Sobald die Abhängigkeit wiederhergestellt ist, ist die Verwendung des MOQ-Frameworks so einfach wie das Erstellen einer Instanz der SampleOptions-Klasse und das Zuweisen dieser Instanz zum Wert.
Hier ist eine Code-Übersicht, wie es aussehen würde.
Sobald der Mock eingerichtet ist, können Sie das Mock-Objekt als an den Konstruktor übergeben
HTH.
Zu Ihrer Information Ich habe ein Git-Repository, das diese beiden Ansätze auf Github / patvin80 beschreibt
quelle
Sie können die Verwendung von MOQ überhaupt vermeiden. Verwenden Sie in Ihren Tests die .json-Konfigurationsdatei. Eine Datei für viele Testklassendateien.
ConfigurationBuilder
In diesem Fall ist die Verwendung in Ordnung .Beispiel für appsetting.json
Beispiel für eine Einstellungszuordnungsklasse:
Beispiel für einen Service, der zum Testen benötigt wird:
NUnit-Testklasse:
quelle
Gegebene Klasse
Person
, diePersonSettings
wie folgt abhängt :IOptions<PersonSettings>
kann verspottet werden undPerson
wie folgt getestet werden:Zu injizieren
IOptions<PersonSettings>
inPerson
anstatt sie explizit auf die Ctor geben, verwenden Sie diesen Code:quelle
Sie können Ihre Optionen jederzeit über Options.Create () erstellen und dann einfach AutoMocker.Use (Optionen) verwenden, bevor Sie die verspottete Instanz des zu testenden Repositorys erstellen. Mit AutoMocker.CreateInstance <> () können Instanzen einfacher erstellt werden, ohne dass Parameter manuell übergeben werden müssen
Ich habe geändert, dass Sie SampleRepo ein wenig sind, um das Verhalten reproduzieren zu können, von dem ich denke, dass Sie es erreichen möchten.
quelle
Hier ist ein weiterer einfacher Weg, der kein Mock benötigt, sondern den OptionsWrapper verwendet:
quelle
Für meine System- und Integrationstests bevorzuge ich eine Kopie / einen Link meiner Konfigurationsdatei im Testprojekt. Und dann benutze ich den ConfigurationBuilder, um die Optionen zu erhalten.
Auf diese Weise kann ich die Konfiguration überall in meinem TestProject verwenden. Für Unit-Tests bevorzuge ich MOQ wie das beschriebene patvin80.
quelle
Stimmen Sie Aleha zu, dass die Verwendung einer Konfigurationsdatei testSettings.json wahrscheinlich besser ist. Und anstatt die IOption zu injizieren, können Sie einfach die echten SampleOptions in Ihren Klassenkonstruktor injizieren. Wenn Sie die Klasse einem Komponententest unterziehen, können Sie Folgendes in einem Fixture oder erneut nur im Testklassenkonstruktor tun:
quelle