webentwicklung-frage-antwort-db.com.de

So richten Sie Mock of IConfigurationRoot ein, um einen Wert zurückzugeben

Ich habe IConfigurationRoute verwendet, um auf ein Verzeichnis wie dieses zuzugreifen.

if (type == "error") directory = _config.GetValue<string>("Directories:SomeDirectory");

_config ist IConfigurationRoot, das in den Konstruktor eingefügt wird.

Ich habe den folgenden Weg versucht, um es zu verspotten.

        var mockConfigurationRoot = new Mock<IConfigurationRoot>();
        mockConfigurationRoot.Setup(c => c.GetValue<string>("Directories: SomeDirectory"))
            .Returns("SomeDirectory")
            .Verifiable();
        var config = mockConfigurationRoot.Object;

Das Problem ist, dass Xunit beim Ausführen des Tests die Ausnahmebedingung "Spruch" auslöst

"System.NotSupportedException: Ausdruck verweist auf eine Methode, die nicht zum verspotteten Objekt gehört."

Wie kann ich dieses Problem lösen?

18
Virodh

Ich habe es mit der SetupGet-Methode wie folgt gemacht. Es funktioniert bei mir, hoffe es hilft.

_configurationRoot = new Mock<IConfigurationRoot>();
_configurationRoot.SetupGet(x => x[It.IsAny<string>()]).Returns("the string you want to return");
26
user3130628
  1. Kopieren Sie die Datei appSettings.json in das Stammverzeichnis Ihres Testprojekts und markieren Sie die Eigenschaft als Inhalt und kopieren Sie sie, falls sie neuer ist.

  2. var builder = new ConfigurationBuilder()
          .SetBasePath(Directory.GetCurrentDirectory())
          .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
          .AddEnvironmentVariables();
    ConfigurationManager.Configuration = builder.Build();
    
  3. ConfigurationManager ist eine Klasse mit einer statischen Eigenschaft Configuration. Auf diese Weise kann die gesamte Anwendung einfach als ConfigurationManager.Configuration [] darauf zugreifen.

Ich denke, die Art und Weise, wie Sie dies tun würden, besteht darin, verspottbare Proxy-Erweiterungsmethoden zu erstellen und diese stattdessen zu verwenden. Lokale Erweiterungsmethoden können externe Methoden überschreiben, sodass Sie Ihre eigene Erweiterungsklasse erstellen können:

public static class ConfigurationExtensions
{
    public static IConfigurationProxy Proxy = new ConfigurationProxy();
    public static T GetValue<T>(this IConfigurationRoot config, string key) => Proxy.GetValue<T>(config, key);
}

Richten Sie dann Ihren Proxy ein:

public class ConfigurationProxy : IConfigurationProxy
{
    public T GetValue<T>(IConfigurationRoot config, string key) => config.GetValue<T>(key);
}

Fügen Sie nun in jeder Klasse, in der Sie verspottbare Erweiterungsmethoden verwenden möchten, einen statischen Konstruktor hinzu:

static MyClass()
{
    ConfigurationExtensions.Proxy = new ConfigurationProxy();
}

Oder

static MyClass_Tests()
{
    ConfigurationExtensions.Proxy = Mock.Of<IConfigurationProxy>();
}

Waschen, spülen, wiederholen Sie für jede Verlängerungsmethode, die Sie verwenden müssen. Weitere Erklärungen finden Sie hier: http://blogs.clariusconsulting.net/kzu/how-to-design-a-unit-testable-domain-model-with-entity-framework-code-first/

Falls es hilfreich ist, können Sie auch den Getter des Wörterbuchs verspotten:

mockConfigurationRoot.SetupGet(m => m["ConnectionStrings:Repository"]).Returns("bogus");
1
Chris D