RazorStránky testů jednotek v ASP.NET Core
ASP.NET Core podporuje testy jednotek aplikací Razor Pages. Testy vrstvy dal (Data Access Layer) a stránkových modelů pomáhají zajistit:
- Části aplikace Pages fungují nezávisle a společně jako Razor celek při konstrukci aplikace.
- Třídy a metody mají omezené rozsahy zodpovědnosti.
- Existuje další dokumentace k chování aplikace.
- Regrese, což jsou chyby vyúscené aktualizacemi kódu, se nacházejí během automatizovaného sestavování a nasazování.
Toto téma předpokládá, že máte základní znalosti o aplikacích Pages a Razor testech jednotek. Pokud aplikace Pages nebo koncepty testů ještě nevíte, projděte Razor si následující témata:
- Úvod do Razor stránek v ASP.NET Core
- Kurz: Začínáme se Razor stránkami v ASP.NET Core
- Testování částí jazyka C# v .NET Core pomocí příkazu dotnet test a xUnit
Zobrazení nebo stažení ukázkového kódu (stažení)
Ukázkový projekt se skládá ze dvou aplikací:
| Aplikace | Project složka | Description |
|---|---|---|
| Aplikace zpráv | src/ Razor PagesTestSample | Umožňuje uživateli přidat zprávu, odstranit jednu zprávu, odstranit všechny zprávy a analyzovat zprávy (najít průměrný počet slov na zprávu). |
| Testovací aplikace | tests/ Razor PagesTestSample.Tests | Slouží k testování modelu stránek DAL a Index aplikace zpráv. |
Testy lze spustit pomocí integrovaných testovacích funkcí integrovaného vývojového prostředí, jako je Visual Studio nebo Visual Studio pro Mac. Pokud používáte Visual Studio Code nebo příkazového řádku, spusťte následující příkaz na příkazovém řádku ve složce tests/ Razor PagesTestSample.Tests:
dotnet test
Organizace aplikace zpráv
Aplikace zpráv je systém Razor zpráv Pages s následujícími charakteristikami:
- Stránka Index aplikace (Pages/Index.cshtml a Pages/Index.cshtml.cs) poskytuje metody uživatelského rozhraní a modelu stránky pro řízení přidávání, odstraňování a analýzy zpráv (vyhledání průměrného počtu slov na zprávu).
- Zprávu popisuje třída
Message(Data/Message.cs) se dvěma vlastnostmi:Id(klíč) aText(zpráva). VlastnostTextje povinná a omezená na 200 znaků. - Zprávy se ukládají pomocí Entity Framework databáze v paměti†.
- Aplikace obsahuje dal ve své třídě kontextu databáze
AppDbContext(Data/AppDbContext.cs). Metody DAL jsou označenévirtual, což umožňuje napodomenování metod pro použití v testech. - Pokud je databáze při spuštění aplikace prázdná, inicializuje se úložiště zpráv se třemi zprávami. Tyto dosycené zprávy se používají také v testech.
†tématu EF, Test with InMemory, vysvětluje, jak používat databázi v paměti pro testy pomocí MSTestu. Toto téma používá testovací rozhraní xUnit. Koncepty testů a implementace testů v různých testovacích architekturách jsou podobné, ale nejsou identické.
I když ukázková aplikace vzor úložiště nevyu i používá a není efektivním příkladem vzoru UoW (Unit of Work),Pages podporuje tyto vzory Razor vývoje. Další informace najdete v tématu Návrh vrstvy trvalosti infrastruktury a Logika kontroleru testů v ASP.NET Core (ukázka implementuje vzor úložiště).
Otestování organizace aplikace
Testovací aplikace je konzolová aplikace ve složce tests/ Razor PagesTestSample.Tests.
| Test složky aplikace | Description |
|---|---|
| UnitTests |
|
| Nástroje | Obsahuje metodu, která se používá k vytvoření nových možností kontextu databáze pro každý test jednotek DAL, aby se databáze pro každý test resetuje na svou základní TestDbContextOptions podmínku. |
Testovací rozhraní je xUnit. Rozhraní napodokování objektů je Moq.
Testy jednotek vrstvy přístupu k datům (DAL)
Aplikace zpráv má dal se čtyřmi metodami obsaženými ve třídě AppDbContext (src/ Razor PagesTestSample/Data/AppDbContext.cs). Každá metoda má v testovací aplikaci jeden nebo dva testy jednotek.
| Metoda DAL | Funkce |
|---|---|
GetMessagesAsync |
Získá z List<Message> databáze seřazené podle Text vlastnosti . |
AddMessageAsync |
Přidá Message do databáze . |
DeleteAllMessagesAsync |
Odstraní všechny Message položky z databáze. |
DeleteMessageAsync |
Odstraní jeden z Message databáze pomocí Id . |
Testy jednotek dal vyžadují DbContextOptions při vytváření nového pro každý AppDbContext test. Jedním z přístupů k DbContextOptions vytvoření pro každý test je použití DbContextOptionsBuilder :
var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("InMemoryDb");
using (var db = new AppDbContext(optionsBuilder.Options))
{
// Use the db here in the unit test.
}
Problémem tohoto přístupu je, že každý test obdrží databázi v jiném stavu, ve které ji předchozí test opustil. To může být problematické při pokusu o zápis atomických testů jednotek, které nejsou vzájemně v konfliktu. Pokud chcete vynutit použití nového kontextu databáze pro každý test, zadejte instanci založenou na AppDbContext DbContextOptions novém poskytovateli služeb. Testovací aplikace ukazuje, jak to provést pomocí metody třídy Utilities TestDbContextOptions (tests/ Razor PagesTestSample.Tests/Utilities/Utilities.cs):
public static DbContextOptions<AppDbContext> TestDbContextOptions()
{
// Create a new service provider to create a new in-memory database.
var serviceProvider = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();
// Create a new options instance using an in-memory database and
// IServiceProvider that the context should resolve all of its
// services from.
var builder = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("InMemoryDb")
.UseInternalServiceProvider(serviceProvider);
return builder.Options;
}
Použití příkazu v testech jednotek DAL umožňuje, aby se každý test spouštěl DbContextOptions atomicky s novou instancí databáze:
using (var db = new AppDbContext(Utilities.TestDbContextOptions()))
{
// Use the db here in the unit test.
}
Každá testovací metoda ve DataAccessLayerTest třídě (UnitTests/DataAccessLayerTest.cs) má podobný vzor Arrange-Act-Assert:
- Uspořádat: Databáze je nakonfigurovaná pro test nebo je definovaný očekávaný výsledek.
- Jednat: Test se provede.
- Kontrolní výraz: Kontrolní výrazy určují, jestli je výsledek testu úspěšný.
Například metoda zodpovídá za odebrání jedné zprávy identifikované její DeleteMessageAsync Id (src/ Razor PagesTestSample/Data/AppDbContext.cs):
public async virtual Task DeleteMessageAsync(int id)
{
var message = await Messages.FindAsync(id);
if (message != null)
{
Messages.Remove(message);
await SaveChangesAsync();
}
}
Pro tuto metodu existují dva testy. Jeden test zkontroluje, zda metoda odstraní zprávu, když je zpráva přítomna v databázi. Druhá metoda testuje, jestli se databáze nezmění, pokud zpráva k odstranění Id neexistuje. Metoda DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFound je znázorněna níže:
[Fact]
public async Task DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFound()
{
using (var db = new AppDbContext(Utilities.TestDbContextOptions()))
{
// Arrange
var seedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(seedMessages);
await db.SaveChangesAsync();
var recId = 1;
var expectedMessages =
seedMessages.Where(message => message.Id != recId).ToList();
// Act
await db.DeleteMessageAsync(recId);
// Assert
var actualMessages = await db.Messages.AsNoTracking().ToListAsync();
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));
}
}
Nejprve metoda provede krok Uspořádat, kde probíhá příprava na krok Act. Zprávy dosytování se získávají a uchují v seedMessages . Zprávy předsídky se ukládají do databáze. Zpráva s příznakem Id je 1 nastavená pro odstranění. Při spuštění metody by očekávané zprávy měly mít všechny zprávy s výjimkou zprávy DeleteMessageAsync s . Id 1 Proměnná expectedMessages představuje tento očekávaný výsledek.
// Arrange
var seedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(seedMessages);
await db.SaveChangesAsync();
var recId = 1;
var expectedMessages =
seedMessages.Where(message => message.Id != recId).ToList();
Metoda funguje: DeleteMessageAsync Metoda se spustí a předá recId metodu 1 z :
// Act
await db.DeleteMessageAsync(recId);
Nakonec metoda získá z kontextu a porovná ji s tvrzením, že jsou si Messages expectedMessages tyto dva rovny:
// Assert
var actualMessages = await db.Messages.AsNoTracking().ToListAsync();
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));
Abychom mohli porovnat, že jsou List<Message> tyto dva stejné:
- Zprávy jsou seřazené podle
Id. - Páry zpráv jsou porovnány s
Textvlastností .
Podobná testovací metoda zkontroluje výsledek pokusu o odstranění zprávy, která DeleteMessageAsync_NoMessageIsDeleted_WhenMessageIsNotFound neexistuje. V takovém případě by se očekávané zprávy v databázi měly rovnat skutečným zprávám po DeleteMessageAsync spuštění metody. Obsah databáze by se neměl měnit:
[Fact]
public async Task DeleteMessageAsync_NoMessageIsDeleted_WhenMessageIsNotFound()
{
using (var db = new AppDbContext(Utilities.TestDbContextOptions()))
{
// Arrange
var expectedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(expectedMessages);
await db.SaveChangesAsync();
var recId = 4;
// Act
try
{
await db.DeleteMessageAsync(recId);
}
catch
{
// recId doesn't exist
}
// Assert
var actualMessages = await db.Messages.AsNoTracking().ToListAsync();
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));
}
}
Testy jednotek metod stránkového modelu
Další sada testů jednotek je zodpovědná za testy metod modelu stránek. V aplikaci zpráv se modely indexových stránek nacházejí ve třídě IndexModel v souboru src/ Razor PagesTestSample/Pages/Index.cshtml.cs.
| Metoda modelu stránky | Funkce |
|---|---|
OnGetAsync |
Získá zprávy z DAL pro uživatelské rozhraní pomocí GetMessagesAsync metody . |
OnPostAddMessageAsync |
Pokud je model ModelState platný, zavolá AddMessageAsync metodu pro přidání zprávy do databáze. |
OnPostDeleteAllMessagesAsync |
Voláním DeleteAllMessagesAsync metody odstraníte všechny zprávy v databázi. |
OnPostDeleteMessageAsync |
Provede příkaz DeleteMessageAsync k odstranění zprávy se Id zadaným parametrem . |
OnPostAnalyzeMessagesAsync |
Pokud je v databázi jedna nebo více zpráv, vypočítá průměrný počet slov na zprávu. |
Metody modelu stránky se testují pomocí sedmi testů ve třídě IndexPageTests (tests/ Razor PagesTestSample.Tests/UnitTests/IndexPageTests.cs). Tyto testy používají známý vzor Arrange-Assert-Act. Tyto testy se zaměřují na:
- Určení, zda metody dodržují správné chování, pokud je model ModelState neplatný.
- Potvrzením metody se vytvoří správná metoda IActionResult .
- Kontrola správných přiřazení hodnot vlastností
Tato skupina testů často napodobuje metody DAL k vytvoření očekávaných dat pro krok Act, kde se spustí metoda modelu stránky. Například metoda GetMessagesAsync je AppDbContext napodobována, aby se vyprodukoval výstup. Když metoda modelu stránky spustí tuto metodu, napodobování vrátí výsledek. Data nepochádí z databáze. Tím se vytvoří předvídatelné a spolehlivé testovací podmínky pro použití dal v testech stránkového modelu.
Test OnGetAsync_PopulatesThePageModel_WithAListOfMessages ukazuje, jak GetMessagesAsync je metoda napodobována pro model stránky:
var mockAppDbContext = new Mock<AppDbContext>(optionsBuilder.Options);
var expectedMessages = AppDbContext.GetSeedingMessages();
mockAppDbContext.Setup(
db => db.GetMessagesAsync()).Returns(Task.FromResult(expectedMessages));
var pageModel = new IndexModel(mockAppDbContext.Object);
Při OnGetAsync spuštění metody v kroku Act volá metodu modelu GetMessagesAsync stránky.
Krok Act testu jednotek (tests/ Razor PagesTestSample.Tests/UnitTests/IndexPageTests.cs):
// Act
await pageModel.OnGetAsync();
IndexPage metoda modelu stránky OnGetAsync (src/ Razor PagesTestSample/Pages/Index.cshtml.cs):
public async Task OnGetAsync()
{
Messages = await _db.GetMessagesAsync();
}
Metoda GetMessagesAsync v sadě DAL nevrací výsledek volání této metody. Napodocená verze metody vrátí výsledek.
V Assert tomto kroku jsou skutečné zprávy ( actualMessages ) přiřazeny z Messages vlastnosti modelu stránky. Kontrola typu se provádí také při přiřazení zpráv. Očekávané a skutečné zprávy se porovnávají podle jejich Text vlastností. Test prosadí, že List<Message> dvě instance obsahují stejné zprávy.
// Assert
var actualMessages = Assert.IsAssignableFrom<List<Message>>(pageModel.Messages);
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));
Další testy v této skupině vytvářejí objekty modelu stránky, které zahrnují , , a pro vytvoření DefaultHttpContext ModelStateDictionary objektů , a ActionContext PageContext ViewDataDictionary PageContext . Jsou užitečné při provádění testů. Aplikace zpráv například zjistí chybu s příkazem a zkontroluje, že se při spuštění ModelState AddModelError vrátí PageResult OnPostAddMessageAsync platná hodnota:
[Fact]
public async Task OnPostAddMessageAsync_ReturnsAPageResult_WhenModelStateIsInvalid()
{
// Arrange
var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("InMemoryDb");
var mockAppDbContext = new Mock<AppDbContext>(optionsBuilder.Options);
var expectedMessages = AppDbContext.GetSeedingMessages();
mockAppDbContext.Setup(db => db.GetMessagesAsync()).Returns(Task.FromResult(expectedMessages));
var httpContext = new DefaultHttpContext();
var modelState = new ModelStateDictionary();
var actionContext = new ActionContext(httpContext, new RouteData(), new PageActionDescriptor(), modelState);
var modelMetadataProvider = new EmptyModelMetadataProvider();
var viewData = new ViewDataDictionary(modelMetadataProvider, modelState);
var tempData = new TempDataDictionary(httpContext, Mock.Of<ITempDataProvider>());
var pageContext = new PageContext(actionContext)
{
ViewData = viewData
};
var pageModel = new IndexModel(mockAppDbContext.Object)
{
PageContext = pageContext,
TempData = tempData,
Url = new UrlHelper(actionContext)
};
pageModel.ModelState.AddModelError("Message.Text", "The Text field is required.");
// Act
var result = await pageModel.OnPostAddMessageAsync();
// Assert
Assert.IsType<PageResult>(result);
}
Další zdroje informací
- Testování částí jazyka C# v .NET Core pomocí příkazu dotnet test a xUnit
- Logika kontroleru testů v ASP.NET Core
- Testování částí kódu (Visual Studio)
- Integrační testy v ASP.NET Core
- xUnit.net
- Vytvoření kompletního řešení .NET Core v systému macOS pomocí sady Visual Studio pro Mac
- Začínáme s xUnit.net: Použití .NET Core s příkazový řádek sady .NET SDK
- Moq
- Rychlý start pro Moq
ASP.NET Core podporuje testy jednotek aplikací Razor Pages. Testy vrstvy dal (Data Access Layer) a stránkových modelů pomáhají zajistit:
- Části aplikace Razor Pages fungují nezávisle a společně jako celek při konstrukci aplikace.
- Třídy a metody mají omezené rozsahy zodpovědnosti.
- Existuje další dokumentace k chování aplikace.
- Regrese, což jsou chyby vyúscené aktualizacemi kódu, se nacházejí během automatizovaného sestavování a nasazování.
Toto téma předpokládá, že máte základní znalosti o aplikacích Pages a Razor testech jednotek. Pokud aplikace Pages nebo koncepty testů ještě nevíte, projděte Razor si následující témata:
- Úvod do Razor stránek v ASP.NET Core
- Kurz: Začínáme se Razor stránkami v ASP.NET Core
- Testování částí jazyka C# v .NET Core pomocí příkazu dotnet test a xUnit
Zobrazení nebo stažení ukázkového kódu (stažení)
Ukázkový projekt se skládá ze dvou aplikací:
| Aplikace | Project složka | Description |
|---|---|---|
| Aplikace zpráv | src/ Razor PagesTestSample | Umožňuje uživateli přidat zprávu, odstranit jednu zprávu, odstranit všechny zprávy a analyzovat zprávy (najít průměrný počet slov na zprávu). |
| Testovací aplikace | tests/ Razor PagesTestSample.Tests | Slouží k testování modelu stránek DAL a Index aplikace zpráv. |
Testy lze spustit pomocí integrovaných testovacích funkcí integrovaného vývojového prostředí, jako je Visual Studio nebo Visual Studio pro Mac. Pokud používáte Visual Studio Code nebo příkazového řádku, spusťte následující příkaz na příkazovém řádku ve složce tests/ Razor PagesTestSample.Tests:
dotnet test
Organizace aplikace zpráv
Aplikace zpráv je systém Razor zpráv Pages s následujícími charakteristikami:
- Stránka Index aplikace (Pages/Index.cshtml a Pages/Index.cshtml.cs) poskytuje metody uživatelského rozhraní a modelu stránky pro řízení přidávání, odstraňování a analýzy zpráv (vyhledání průměrného počtu slov na zprávu).
- Zprávu popisuje třída
Message(Data/Message.cs) se dvěma vlastnostmi:Id(klíč) aText(zpráva). VlastnostTextje povinná a omezená na 200 znaků. - Zprávy se ukládají pomocí Entity Framework databáze v paměti†.
- Aplikace obsahuje dal ve své třídě kontextu databáze
AppDbContext(Data/AppDbContext.cs). Metody DAL jsou označenévirtual, což umožňuje napodomenování metod pro použití v testech. - Pokud je databáze při spuštění aplikace prázdná, inicializuje se úložiště zpráv se třemi zprávami. Tyto dosycené zprávy se používají také v testech.
†tématu EF, Test with InMemory, vysvětluje, jak používat databázi v paměti pro testy pomocí MSTestu. Toto téma používá testovací rozhraní xUnit. Koncepty testů a implementace testů v různých testovacích architekturách jsou podobné, ale nejsou identické.
I když ukázková aplikace vzor úložiště nevyu i používá a není efektivním příkladem vzoru UoW (Unit of Work),Pages podporuje tyto vzory Razor vývoje. Další informace najdete v tématu Návrh vrstvy trvalosti infrastruktury a Logika kontroleru testů v ASP.NET Core (ukázka implementuje vzor úložiště).
Otestování organizace aplikace
Testovací aplikace je konzolová aplikace ve složce tests/ Razor PagesTestSample.Tests.
| Test složky aplikace | Description |
|---|---|
| UnitTests |
|
| Nástroje | Obsahuje metodu, která se používá k vytvoření nových možností kontextu databáze pro každý test jednotek DAL, aby se databáze obnovuje na svou základní TestDbContextOptions podmínku pro každý test. |
Testovací rozhraní je xUnit. Rozhraní napodokování objektů je Moq.
Testy jednotek vrstvy přístupu k datům (DAL)
Aplikace zpráv má dal se čtyřmi metodami obsaženými ve třídě AppDbContext (src/ Razor PagesTestSample/Data/AppDbContext.cs). Každá metoda má v testovací aplikaci jeden nebo dva testy jednotek.
| Metoda DAL | Funkce |
|---|---|
GetMessagesAsync |
Získá z List<Message> databáze seřazené podle Text vlastnosti . |
AddMessageAsync |
Přidá Message do databáze . |
DeleteAllMessagesAsync |
Odstraní všechny Message položky z databáze. |
DeleteMessageAsync |
Odstraní jeden z Message databáze pomocí Id . |
Testy jednotek dal vyžadují DbContextOptions při vytváření nového pro každý AppDbContext test. Jedním z přístupů k DbContextOptions vytvoření pro každý test je použití DbContextOptionsBuilder :
var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("InMemoryDb");
using (var db = new AppDbContext(optionsBuilder.Options))
{
// Use the db here in the unit test.
}
Problémem tohoto přístupu je, že každý test obdrží databázi v jiném stavu, ve které ji předchozí test opustil. To může být problematické při pokusu o zápis atomických testů jednotek, které nejsou vzájemně v konfliktu. Pokud chcete vynutit použití nového kontextu databáze pro každý test, zadejte instanci založenou na AppDbContext DbContextOptions novém poskytovateli služeb. Testovací aplikace ukazuje, jak to provést pomocí metody třídy Utilities TestDbContextOptions (tests/ Razor PagesTestSample.Tests/Utilities/Utilities.cs):
public static DbContextOptions<AppDbContext> TestDbContextOptions()
{
// Create a new service provider to create a new in-memory database.
var serviceProvider = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();
// Create a new options instance using an in-memory database and
// IServiceProvider that the context should resolve all of its
// services from.
var builder = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("InMemoryDb")
.UseInternalServiceProvider(serviceProvider);
return builder.Options;
}
Použití příkazu v testech jednotek DAL umožňuje, aby se každý test spouštěl DbContextOptions atomicky s novou instancí databáze:
using (var db = new AppDbContext(Utilities.TestDbContextOptions()))
{
// Use the db here in the unit test.
}
Každá testovací metoda ve DataAccessLayerTest třídě (UnitTests/DataAccessLayerTest.cs) má podobný vzor Arrange-Act-Assert:
- Uspořádat: Databáze je nakonfigurovaná pro test nebo je definovaný očekávaný výsledek.
- Jednat: Test se provede.
- Kontrolní výraz: Kontrolní výrazy určují, jestli je výsledek testu úspěšný.
Například DeleteMessageAsync Metoda zodpovídá za odebrání jedné zprávy identifikované její Id (Src/ Razor PagesTestSample/data/AppDbContext. cs):
public async virtual Task DeleteMessageAsync(int id)
{
var message = await Messages.FindAsync(id);
if (message != null)
{
Messages.Remove(message);
await SaveChangesAsync();
}
}
Existují dva testy pro tuto metodu. Jeden test kontroluje, zda metoda odstraní zprávu, když se zpráva nachází v databázi. Druhá metoda Testuje, že se databáze nemění, pokud zpráva Id pro odstranění neexistuje. DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFoundMetoda je zobrazena níže:
[Fact]
public async Task DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFound()
{
using (var db = new AppDbContext(Utilities.TestDbContextOptions()))
{
// Arrange
var seedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(seedMessages);
await db.SaveChangesAsync();
var recId = 1;
var expectedMessages =
seedMessages.Where(message => message.Id != recId).ToList();
// Act
await db.DeleteMessageAsync(recId);
// Assert
var actualMessages = await db.Messages.AsNoTracking().ToListAsync();
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));
}
}
Nejprve metoda provede krok uspořádat, kde se provádí příprava pro krok Act. Zprávy o osazení se získávají a uchovávají v seedMessages . Počáteční zprávy se ukládají do databáze nástroje. Zpráva s objektem Id 1 je nastavena pro odstranění. Při DeleteMessageAsync spuštění metody musí mít očekávané zprávy všechny zprávy s výjimkou jednoho s Id 1 . expectedMessagesProměnná představuje tento očekávaný výsledek.
// Arrange
var seedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(seedMessages);
await db.SaveChangesAsync();
var recId = 1;
var expectedMessages =
seedMessages.Where(message => message.Id != recId).ToList();
Metoda funguje: DeleteMessageAsync Metoda je prováděna předáním v recId 1 :
// Act
await db.DeleteMessageAsync(recId);
Nakonec Metoda získá Messages z kontextu a porovná ho s expectedMessages kontrolním výrazem, že obě jsou stejné:
// Assert
var actualMessages = await db.Messages.AsNoTracking().ToListAsync();
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));
Aby bylo možné porovnat tyto dvě List<Message> stejné:
- Zprávy jsou seřazeny podle
Id. - Páry zpráv jsou porovnány s
Textvlastností.
Podobná testovací metoda DeleteMessageAsync_NoMessageIsDeleted_WhenMessageIsNotFound kontroluje výsledek pokusu o odstranění neexistující zprávy. V takovém případě by měly být očekávané zprávy v databázi rovny skutečným zprávám po DeleteMessageAsync provedení metody. Obsah databáze by neměl být změněn:
[Fact]
public async Task DeleteMessageAsync_NoMessageIsDeleted_WhenMessageIsNotFound()
{
using (var db = new AppDbContext(Utilities.TestDbContextOptions()))
{
// Arrange
var expectedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(expectedMessages);
await db.SaveChangesAsync();
var recId = 4;
// Act
await db.DeleteMessageAsync(recId);
// Assert
var actualMessages = await db.Messages.AsNoTracking().ToListAsync();
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));
}
}
Testování částí metod modelu stránky
Další sada testů jednotek zodpovídá za testy metod modelu stránky. V aplikaci zprávy jsou modely stránek indexu nalezeny ve IndexModel třídě v Src/ Razor PagesTestSample/pages/index. cshtml. cs.
| Metoda modelu stránky | Funkce |
|---|---|
OnGetAsync |
Získá zprávy z DAL pro uživatelské rozhraní pomocí GetMessagesAsync metody. |
OnPostAddMessageAsync |
Pokud je ModelState platný, volání AddMessageAsync pro přidání zprávy do databáze. |
OnPostDeleteAllMessagesAsync |
Volá DeleteAllMessagesAsync se, aby se odstranily všechny zprávy v databázi. |
OnPostDeleteMessageAsync |
Provede DeleteMessageAsync odstranění zprávy se Id zadaným. |
OnPostAnalyzeMessagesAsync |
Pokud je v databázi jedna nebo více zpráv, vypočítá průměrný počet slov na jednu zprávu. |
Metody modelu stránky jsou testovány pomocí sedmi testů ve IndexPageTests třídě (Tests/ Razor PagesTestSample. Tests/UnitTests/IndexPageTests. cs). Testy používají známý vzor uspořádání a vyhodnocení – Act. Tyto testy se zaměřují na:
- Určení, zda metody dodrží správné chování, pokud je ModelState neplatné.
- Potvrzení metod vyprodukuje správné IActionResult .
- Kontroluje se, jestli jsou přiřazení hodnot vlastností správně vytvořená.
Tato skupina testů často napodobuje metody DAL, aby vytvořila očekávaná data pro krok Act, kde je spuštěna metoda modelu stránky. Například GetMessagesAsync Metoda AppDbContext je napodobná, aby vytvořila výstup. Když metoda modelu stránky spustí tuto metodu, vrátí výsledek. Data nepocházejí z databáze. Tím se vytvoří předvídatelné a spolehlivé testovací podmínky pro použití DAL v testech modelu stránky.
OnGetAsync_PopulatesThePageModel_WithAListOfMessagesTest ukazuje, jak je metoda popsána GetMessagesAsync pro model stránky:
var mockAppDbContext = new Mock<AppDbContext>(optionsBuilder.Options);
var expectedMessages = AppDbContext.GetSeedingMessages();
mockAppDbContext.Setup(
db => db.GetMessagesAsync()).Returns(Task.FromResult(expectedMessages));
var pageModel = new IndexModel(mockAppDbContext.Object);
Při OnGetAsync spuštění metody v kroku Act volá metodu modelu stránky GetMessagesAsync .
Krok testu jednotek krok (Tests/ Razor PagesTestSample. Tests/UnitTests/IndexPageTests. cs):
// Act
await pageModel.OnGetAsync();
IndexPage Metoda modelu stránky OnGetAsync (Src/ Razor PagesTestSample/pages/index. cshtml. cs):
public async Task OnGetAsync()
{
Messages = await _db.GetMessagesAsync();
}
GetMessagesAsyncMetoda v metodě dal nevrací výsledek pro toto volání metody. Napodobovaná verze metody vrátí výsledek.
V Assert kroku jsou skutečné zprávy ( actualMessages ) přiřazeny z Messages vlastnosti modelu stránky. Při přiřazení zpráv se také provádí ověření typu. Očekávané a skutečné zprávy jsou porovnány podle jejich Text vlastností. Test vyhodnotí, že dvě List<Message> instance obsahují stejné zprávy.
// Assert
var actualMessages = Assert.IsAssignableFrom<List<Message>>(pageModel.Messages);
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));
Jiné testy v této skupině vytvoří objekty modelu stránky, které obsahují DefaultHttpContext , a ModelStateDictionary , ActionContext k vytvoření, a PageContext ViewDataDictionary PageContext . Ty jsou užitečné při provádění testů. Například aplikace zprávy naváže ModelState chybu s AddModelError cílem ověřit, že PageResult je při spuštění vrácena platná OnPostAddMessageAsync :
[Fact]
public async Task OnPostAddMessageAsync_ReturnsAPageResult_WhenModelStateIsInvalid()
{
// Arrange
var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("InMemoryDb");
var mockAppDbContext = new Mock<AppDbContext>(optionsBuilder.Options);
var expectedMessages = AppDbContext.GetSeedingMessages();
mockAppDbContext.Setup(db => db.GetMessagesAsync()).Returns(Task.FromResult(expectedMessages));
var httpContext = new DefaultHttpContext();
var modelState = new ModelStateDictionary();
var actionContext = new ActionContext(httpContext, new RouteData(), new PageActionDescriptor(), modelState);
var modelMetadataProvider = new EmptyModelMetadataProvider();
var viewData = new ViewDataDictionary(modelMetadataProvider, modelState);
var tempData = new TempDataDictionary(httpContext, Mock.Of<ITempDataProvider>());
var pageContext = new PageContext(actionContext)
{
ViewData = viewData
};
var pageModel = new IndexModel(mockAppDbContext.Object)
{
PageContext = pageContext,
TempData = tempData,
Url = new UrlHelper(actionContext)
};
pageModel.ModelState.AddModelError("Message.Text", "The Text field is required.");
// Act
var result = await pageModel.OnPostAddMessageAsync();
// Assert
Assert.IsType<PageResult>(result);
}
Další zdroje informací
- Testování částí C# v .NET Core pomocí příkazu dotnet test a xUnit
- Logika kontroleru testů v ASP.NET Core
- testování částí kódu (Visual Studio)
- Integrační testy v ASP.NET Core
- xUnit.net
- Vytvoření kompletního řešení .NET Core v systému macOS pomocí sady Visual Studio pro Mac
- Začínáme s xUnit.net: použití .NET Core s příkazovým řádkem sady .NET SDK
- Moq
- Rychlý Start MOQ
- JustMockLite: podobná architektura pro vývojáře na platformě .NET. (Společnost Microsoft nespravuje ani nepodporuje.)