2017-11-25 157 views
6

W jaki sposób ludzie testują swoje klasy Startup.cs w aplikacji .NET Core 2? Wydaje się, że cała funkcjonalność została dostarczona przez metody Static Extensions, które nie są możliwe do wykonania?Jak testować urządzenie Startup.cs w rdzeniu .NET

Jeśli wziąć tę metodę ConfigureServices na przykład:

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddDbContext<BlogContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); 

    services.AddMvc(); 
} 

Jak mogę napisać testy w celu zapewnienia, że ​​AddDbContext (...) & AddMvc() są nazywane, Wybór realizacji wszystkich tych funkcjonalności poprzez Wydaje się, że metody rozszerzeń sprawiają, że jest to nieopłacalne?

+0

Dla tych przypadków piszę testy integracyjne dostać przetestowany kompletny rurociąg. Możesz użyć some.g. IoC wstrzykuje jakąś funkcjonalność, którą możesz udawać. – DotNetDev

Odpowiedz

6

Cóż, jeśli chcesz sprawdzić, czy metoda rozszerzenia AddDbContext została wywołana na services masz kłopoty. Dobrą rzeczą jest to, że nie powinieneś dokładnie sprawdzać tego faktu.

Startup klasa to aplikacja composition root. A podczas testowania katalogu głównego kompozycji należy sprawdzić, czy rzeczywiście rejestruje wszystkie zależności wymagane do utworzenia obiektów głównych (kontrolerów w przypadku aplikacji ASP.NET Core).

Powiedzmy, że masz następujące Kontroler:

public class TestController : Controller 
{ 
    public TestController(ISomeDependency dependency) 
    { 
    } 
} 

Można spróbować sprawdzając czy Startup został zarejestrowany typ dla ISomeDependency. Ale implementacja ISomeDependency może również wymagać innych zależności, które powinieneś sprawdzić. W końcu kończy się test, który ma tony kontroli dla różnych zależności, ale to faktycznie nie gwarantuje, że rozwiązanie problemu nie spowoduje braku wyjątku zależności. W takim teście nie ma zbyt wiele wartości.

Podejście, które sprawdza się w przypadku testowania korzenia kompozycji, polega na użyciu kontenera do wstrzykiwania prawdziwych zależności. Następnie wywołuję root kompozycji i twierdzę, że rozdzielczość obiektu głównego nie jest generowana.

Nie można go uznać za czysty test jednostkowy, ponieważ używamy innej klasy, która nie jest skrótowa. Ale takie testy, w przeciwieństwie do innych testów integracyjnych, są szybkie i stabilne. I najważniejsze, że przynoszą wartość prawidłowego sprawdzenia dla prawidłowej rejestracji zależności. Jeśli taki test powiedzie się, możesz być pewien, że obiekt zostanie poprawnie utworzony w produkcie.

Oto przykład takiego testu:

[TestMethod] 
public void ConfigureServices_RegistersDependenciesCorrectly() 
{ 
    // Arrange 

    // Setting up the stuff required for Configuration.GetConnectionString("DefaultConnection") 
    Mock<IConfigurationSection> configurationSectionStub = new Mock<IConfigurationSection>(); 
    configurationSectionStub.Setup(x => x["DefaultConnection"]).Returns("TestConnectionString"); 
    Mock<Microsoft.Extensions.Configuration.IConfiguration> configurationStub = new Mock<Microsoft.Extensions.Configuration.IConfiguration>(); 
    configurationStub.Setup(x => x.GetSection("ConnectionStrings")).Returns(configurationSectionStub.Object); 

    IServiceCollection services = new ServiceCollection(); 
    var target = new Startup(configurationStub.Object); 

    // Act 

    target.ConfigureServices(services); 
    // Mimic internal asp.net core logic. 
    services.AddTransient<TestController>(); 

    // Assert 

    var serviceProvider = services.BuildServiceProvider(); 

    var controller = serviceProvider.GetService<TestController>(); 
    Assert.IsNotNull(controller); 
} 
+1

Dzięki CodeFuller, była to konkretna wersja ServiceCollection, której mi brakowało, mogę po prostu pozwolić, aby kolekcja została zbudowana, a następnie sprawdzić poprawność danych wyjściowych, aby potwierdzić, że zostały wykonane prawidłowe połączenia. Niezłe! –