Razor Testy jednotek stránek v ASP.NET Core
ASP.NET Core podporuje testy Razor jednotek aplikací Pages. Testy vrstvy přístupu k datům (DAL) a stránkových modelů pomáhají zajistit:
- Razor Části aplikace Pages fungují nezávisle a společně jako jednotka při vytváření aplikace.
- Třídy a metody mají omezené rozsahy odpovědnosti.
- Existuje další dokumentace k chování aplikace.
- Během automatizovaného sestavování a nasazování se nacházejí regrese, což jsou chyby způsobené aktualizacemi kódu.
V tomto tématu se předpokládá, že máte základní znalosti o aplikacích Razor Pages a testech jednotek. Pokud neznáte Razor aplikace Pages nebo testovací koncepty, projděte si následující témata:
- Úvod do Razor stránek v ASP.NET Core
- Kurz: Začínáme s Razor Pages v ASP.NET Core
- Testování částí V jazyce C# v .NET Core pomocí testu dotnet a xUnit
Zobrazení nebo stažení ukázkového kódu (postup stažení)
Ukázkový projekt se skládá ze dvou aplikací:
Aplikace | Složka projektu | Popis |
---|---|---|
Aplikace zpráv | src/RazorPagesTestSample | 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/RazorPagesTestSample.Tests | Používá se k testování modelu stránky DAL a Index aplikace zpráv. |
Testy je možné spouštět pomocí integrovaných testovacích funkcí integrovaného vývojového prostředí (IDE), například sady Visual Studio. Pokud používáte Visual Studio Code nebo příkazový řádek, spusťte na příkazovém řádku ve složce tests/RazorPagesTestSample.Tests následující příkaz:
dotnet test
Organizace aplikace zpráv
Aplikace zpráv je Razor systém zpráv Pages s následujícími vlastnostmi:
- Indexová stránka aplikace (
Pages/Index.cshtml
aPages/Index.cshtml.cs
) poskytuje metody uživatelského rozhraní a modelu stránek pro řízení sčítání, odstranění a analýzy zpráv (zjištění průměrného počtu slov na zprávu). - Zpráva je popsána
Message
třídou (Data/Message.cs
) se dvěma vlastnostmi:Id
(klíč) aText
(zpráva). VlastnostText
je povinná a omezená na 200 znaků. - Zprávy se ukládají pomocí databáze v paměti entity Framework†.
- Aplikace obsahuje DAL ve své třídě
AppDbContext
kontextu databáze (Data/AppDbContext.cs
). Metody DAL jsou označenyvirtual
, což umožňuje napodobování metod pro použití v testech. - Pokud je databáze při spuštění aplikace prázdná, úložiště zpráv se inicializuje se třemi zprávami. Tyto počáteční zprávy se používají také v testech.
†Pokudování pomocí nástroje InMemory vysvětluje, jak používat databázi v paměti pro testy s msTestem. Toto téma používá testovací architekturu xUnit . Koncepty testů a implementace testů v různých testovacích architekturách jsou podobné, ale ne identické.
I když ukázková aplikace nepoužívá vzor úložiště a není efektivním příkladem modeluRazor Práce (UoW), stránky tyto vzory vývoje podporují. Další informace najdete v tématu Návrh vrstvy trvalosti infrastruktury a logiky kontroleru testů v ASP.NET Core (ukázka implementuje vzor úložiště).
Testovací organizace aplikací
Testovací aplikace je konzolová aplikace uvnitř složky tests/RazorPagesTestSample.Tests .
Testovací složka aplikace | Popis |
---|---|
UnitTests |
|
Nástroje | Obsahuje metodu použitou TestDbContextOptions k vytvoření nových možností kontextu databáze pro každý test jednotek DAL, aby se databáze resetovala na základní podmínku pro každý test. |
Testovací architektura je xUnit. Architektura napodobová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 AppDbContext
ve třídě (src/RazorPagesTestSample/Data/AppDbContext.cs
). Každá metoda má v testovací aplikaci jeden nebo dva testy jednotek.
Metoda DAL | Function |
---|---|
GetMessagesAsync |
List<Message> Získá z databáze seřazené podle Text vlastnosti. |
AddMessageAsync |
Message Přidá do databáze. |
DeleteAllMessagesAsync |
Odstraní všechny Message položky z databáze. |
DeleteMessageAsync |
Odstraní jeden z Message databáze .Id |
Testy jednotek dal vyžadují DbContextOptions při vytváření nového AppDbContext
pro každý test. Jedním z přístupů k vytvoření DbContextOptions
každého testu 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ém s tímto přístupem spočívá v tom, že každý test obdrží databázi v libovolném stavu, který předchozí test opustil. To může být problematické při pokusu o zápis atomických testů jednotek, které vzájemně neruší. Pokud chcete vynutit AppDbContext
použití nového kontextu databáze pro každý test, zadejte DbContextOptions
instanci založenou na novém poskytovateli služeb. Testovací aplikace ukazuje, jak to provést pomocí metody TestDbContextOptions
třídy Utilities
(tests/RazorPagesTestSample.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;
}
DbContextOptions
Použití testů jednotek DAL umožňuje každému testu spustit 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
) se řídí podobným vzorem Arrange-Act-Assert:
- Uspořádání: Databáze je nakonfigurovaná pro test a/nebo je definován očekávaný výsledek.
- Act: Test je proveden.
- Assert: Kontrolní výrazy jsou provedeny k určení, zda je výsledek testu úspěšný.
Metoda je například DeleteMessageAsync
zodpovědná za odebrání jedné zprávy identifikované jejím Id
(src/RazorPagesTestSample/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, že metoda odstraní zprávu, když je zpráva přítomna v databázi. Druhá metoda testuje, že se databáze nezmění, pokud zpráva Id
pro odstranění neexistuje. Metoda DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFound
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 probíhá příprava na krok Act. Počáteční zprávy jsou získány a uloženy v seedMessages
. Počáteční zprávy se ukládají do databáze. Zpráva s parametrem of Id
1
je nastavena pro odstranění. DeleteMessageAsync
Při spuštění metody by očekávané zprávy měly mít všechny zprávy s výjimkou těch, které obsahují .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: Metoda DeleteMessageAsync
se provádí předáváním recId
1
:
// Act
await db.DeleteMessageAsync(recId);
Nakonec metoda získá Messages
z kontextu a porovná ji s expectedMessages
tvrzením, že jsou obě 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));
Chcete-li porovnat, že oba List<Message>
jsou stejné:
- Zprávy jsou seřazeny podle
Id
. - Dvojice zpráv se porovnávají s
Text
vlastností.
Podobná testovací metoda DeleteMessageAsync_NoMessageIsDeleted_WhenMessageIsNotFound
zkontroluje výsledek pokusu o odstranění zprávy, která neexistuje. V tomto případě by se očekávané zprávy v databázi měly po spuštění metody rovnat skutečným zprávům DeleteMessageAsync
. 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
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 modelu stránky
Další sada testů jednotek zodpovídá za testy metod modelu stránky. V aplikaci zpráv jsou modely stránky indexu nalezeny IndexModel
ve třídě v src/RazorPagesTestSample/Pages/Index.cshtml.cs
.
Metoda stránkování modelu | Function |
---|---|
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ání DeleteAllMessagesAsync pro odstranění všech zpráv v databázi |
OnPostDeleteMessageAsync |
DeleteMessageAsync Provede odstranění zprávy se zadaným parametremId . |
OnPostAnalyzeMessagesAsync |
Pokud je jedna nebo více zpráv v databázi, vypočítá průměrný počet slov na zprávu. |
Metody stránkového modelu se testují pomocí sedmi testů ve IndexPageTests
třídě (tests/RazorPagesTestSample.Tests/UnitTests/IndexPageTests.cs
). Testy používají známý vzor Uspořádat-Assert-Act. Tyto testy se zaměřují na:
- Určení, zda metody dodržují správné chování v případě, že ModelState je neplatný.
- Potvrzení metody vytvoří správnou IActionResult.
- Zkontrolujte správnost přiřazení hodnot vlastností.
Tato skupinatestůch Například GetMessagesAsync
metoda je AppDbContext
napodobena k vytvoření výstupu. Když metoda stránkového modelu spustí tuto metodu, vrátí napodobení 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.
Test OnGetAsync_PopulatesThePageModel_WithAListOfMessages
ukazuje, jak GetMessagesAsync
je metoda napodobena 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);
OnGetAsync
Když se metoda spustí v kroku Act, volá metodu modelu GetMessagesAsync
stránky.
Krok zákona o testování jednotek (tests/RazorPagesTestSample.Tests/UnitTests/IndexPageTests.cs
):
// Act
await pageModel.OnGetAsync();
IndexPage
metoda modelu OnGetAsync
stránky (src/RazorPagesTestSample/Pages/Index.cshtml.cs
):
public async Task OnGetAsync()
{
Messages = await _db.GetMessagesAsync();
}
Metoda GetMessagesAsync
v dal nevrací výsledek pro volání této metody. Napodobená verze metody vrátí výsledek.
Assert
V 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é provede kontrola typu. Očekávané a skutečné zprávy se porovnávají podle jejich Text
vlastností. Test tvrdí, ž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));
Další testy v této skupině vytvářejí objekty modelu stránky, které zahrnují DefaultHttpContextobjekty , ModelStateDictionary, ViewDataDictionary
ActionContext PageContext
a , a .PageContext
To je užitečné při provádění testů. Aplikace zpráv například naváže ModelState
chybu s AddModelError cílem zkontrolovat, jestli je při spuštění vrácena OnPostAddMessageAsync
platná PageResult 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ší materiály
ASP.NET Core podporuje testy Razor jednotek aplikací Pages. Testy vrstvy přístupu k datům (DAL) a stránkových modelů pomáhají zajistit:
- Razor Části aplikace Pages fungují nezávisle a společně jako jednotka při vytváření aplikace.
- Třídy a metody mají omezené rozsahy odpovědnosti.
- Existuje další dokumentace k chování aplikace.
- Během automatizovaného sestavování a nasazování se nacházejí regrese, což jsou chyby způsobené aktualizacemi kódu.
V tomto tématu se předpokládá, že máte základní znalosti o aplikacích Razor Pages a testech jednotek. Pokud neznáte Razor aplikace Pages nebo testovací koncepty, projděte si následující témata:
- Úvod do Razor stránek v ASP.NET Core
- Kurz: Začínáme s Razor Pages v ASP.NET Core
- Testování částí V jazyce C# v .NET Core pomocí testu dotnet a xUnit
Zobrazení nebo stažení ukázkového kódu (postup stažení)
Ukázkový projekt se skládá ze dvou aplikací:
Aplikace | Složka projektu | Popis |
---|---|---|
Aplikace zpráv | src/RazorPagesTestSample | 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/RazorPagesTestSample.Tests | Používá se k testování modelu stránky DAL a Index aplikace zpráv. |
Testy je možné spouštět pomocí integrovaných testovacích funkcí integrovaného vývojového prostředí (IDE), například sady Visual Studio. Pokud používáte Visual Studio Code nebo příkazový řádek, spusťte na příkazovém řádku ve složce tests/RazorPagesTestSample.Tests následující příkaz:
dotnet test
Organizace aplikace zpráv
Aplikace zpráv je Razor systém zpráv Pages s následujícími vlastnostmi:
- Indexová stránka aplikace (
Pages/Index.cshtml
aPages/Index.cshtml.cs
) poskytuje metody uživatelského rozhraní a modelu stránek pro řízení sčítání, odstranění a analýzy zpráv (zjištění průměrného počtu slov na zprávu). - Zpráva je popsána
Message
třídou (Data/Message.cs
) se dvěma vlastnostmi:Id
(klíč) aText
(zpráva). VlastnostText
je povinná a omezená na 200 znaků. - Zprávy se ukládají pomocí databáze v paměti entity Framework†.
- Aplikace obsahuje DAL ve své třídě
AppDbContext
kontextu databáze (Data/AppDbContext.cs
). Metody DAL jsou označenyvirtual
, což umožňuje napodobování metod pro použití v testech. - Pokud je databáze při spuštění aplikace prázdná, úložiště zpráv se inicializuje se třemi zprávami. Tyto počáteční zprávy se používají také v testech.
†Pokudování pomocí nástroje InMemory vysvětluje, jak používat databázi v paměti pro testy s msTestem. Toto téma používá testovací architekturu xUnit . Koncepty testů a implementace testů v různých testovacích architekturách jsou podobné, ale ne identické.
I když ukázková aplikace nepoužívá vzor úložiště a není efektivním příkladem modeluRazor Práce (UoW), stránky tyto vzory vývoje podporují. Další informace najdete v tématu Návrh vrstvy trvalosti infrastruktury a logiky kontroleru testů v ASP.NET Core (ukázka implementuje vzor úložiště).
Testovací organizace aplikací
Testovací aplikace je konzolová aplikace uvnitř složky tests/RazorPagesTestSample.Tests .
Testovací složka aplikace | Popis |
---|---|
UnitTests |
|
Nástroje | Obsahuje metodu použitou TestDbContextOptions k vytvoření nových možností kontextu databáze pro každý test jednotek DAL, aby se databáze resetovala na základní podmínku pro každý test. |
Testovací architektura je xUnit. Architektura napodobová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 AppDbContext
ve třídě (src/RazorPagesTestSample/Data/AppDbContext.cs
). Každá metoda má v testovací aplikaci jeden nebo dva testy jednotek.
Metoda DAL | Function |
---|---|
GetMessagesAsync |
List<Message> Získá z databáze seřazené podle Text vlastnosti. |
AddMessageAsync |
Message Přidá do databáze. |
DeleteAllMessagesAsync |
Odstraní všechny Message položky z databáze. |
DeleteMessageAsync |
Odstraní jeden z Message databáze .Id |
Testy jednotek dal vyžadují DbContextOptions při vytváření nového AppDbContext
pro každý test. Jedním z přístupů k vytvoření DbContextOptions
každého testu 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ém s tímto přístupem spočívá v tom, že každý test obdrží databázi v libovolném stavu, který předchozí test opustil. To může být problematické při pokusu o zápis atomických testů jednotek, které vzájemně neruší. Pokud chcete vynutit AppDbContext
použití nového kontextu databáze pro každý test, zadejte DbContextOptions
instanci založenou na novém poskytovateli služeb. Testovací aplikace ukazuje, jak to provést pomocí metody TestDbContextOptions
třídy Utilities
(tests/RazorPagesTestSample.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;
}
DbContextOptions
Použití testů jednotek DAL umožňuje každému testu spustit 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
) se řídí podobným vzorem Arrange-Act-Assert:
- Uspořádání: Databáze je nakonfigurovaná pro test a/nebo je definován očekávaný výsledek.
- Act: Test je proveden.
- Assert: Kontrolní výrazy jsou provedeny k určení, zda je výsledek testu úspěšný.
Metoda je například DeleteMessageAsync
zodpovědná za odebrání jedné zprávy identifikované jejím Id
(src/RazorPagesTestSample/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, že metoda odstraní zprávu, když je zpráva přítomna v databázi. Druhá metoda testuje, že se databáze nezmění, pokud zpráva Id
pro odstranění neexistuje. Metoda DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFound
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 probíhá příprava na krok Act. Počáteční zprávy jsou získány a uloženy v seedMessages
. Počáteční zprávy se ukládají do databáze. Zpráva s parametrem of Id
1
je nastavena pro odstranění. DeleteMessageAsync
Při spuštění metody by očekávané zprávy měly mít všechny zprávy s výjimkou těch, které obsahují .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: Metoda DeleteMessageAsync
se provádí předáváním recId
1
:
// Act
await db.DeleteMessageAsync(recId);
Nakonec metoda získá Messages
z kontextu a porovná ji s expectedMessages
tvrzením, že jsou obě 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));
Chcete-li porovnat, že oba List<Message>
jsou stejné:
- Zprávy jsou seřazeny podle
Id
. - Dvojice zpráv se porovnávají s
Text
vlastností.
Podobná testovací metoda DeleteMessageAsync_NoMessageIsDeleted_WhenMessageIsNotFound
zkontroluje výsledek pokusu o odstranění zprávy, která neexistuje. V tomto případě by se očekávané zprávy v databázi měly po spuštění metody rovnat skutečným zprávům DeleteMessageAsync
. 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));
}
}
Testy jednotek metod modelu stránky
Další sada testů jednotek zodpovídá za testy metod modelu stránky. V aplikaci zpráv jsou modely stránky indexu nalezeny IndexModel
ve třídě v src/RazorPagesTestSample/Pages/Index.cshtml.cs
.
Metoda stránkování modelu | Function |
---|---|
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ání DeleteAllMessagesAsync pro odstranění všech zpráv v databázi |
OnPostDeleteMessageAsync |
DeleteMessageAsync Provede odstranění zprávy se zadaným parametremId . |
OnPostAnalyzeMessagesAsync |
Pokud je jedna nebo více zpráv v databázi, vypočítá průměrný počet slov na zprávu. |
Metody stránkového modelu se testují pomocí sedmi testů ve IndexPageTests
třídě (tests/RazorPagesTestSample.Tests/UnitTests/IndexPageTests.cs
). Testy používají známý vzor Uspořádat-Assert-Act. Tyto testy se zaměřují na:
- Určení, zda metody dodržují správné chování v případě, že ModelState je neplatný.
- Potvrzení metody vytvoří správnou IActionResult.
- Zkontrolujte správnost přiřazení hodnot vlastností.
Tato skupinatestůch Například GetMessagesAsync
metoda je AppDbContext
napodobena k vytvoření výstupu. Když metoda stránkového modelu spustí tuto metodu, vrátí napodobení 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.
Test OnGetAsync_PopulatesThePageModel_WithAListOfMessages
ukazuje, jak GetMessagesAsync
je metoda napodobena 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);
OnGetAsync
Když se metoda spustí v kroku Act, volá metodu modelu GetMessagesAsync
stránky.
Krok zákona o testování jednotek (tests/RazorPagesTestSample.Tests/UnitTests/IndexPageTests.cs
):
// Act
await pageModel.OnGetAsync();
IndexPage
metoda modelu OnGetAsync
stránky (src/RazorPagesTestSample/Pages/Index.cshtml.cs
):
public async Task OnGetAsync()
{
Messages = await _db.GetMessagesAsync();
}
Metoda GetMessagesAsync
v dal nevrací výsledek pro volání této metody. Napodobená verze metody vrátí výsledek.
Assert
V 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é provede kontrola typu. Očekávané a skutečné zprávy se porovnávají podle jejich Text
vlastností. Test tvrdí, ž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));
Další testy v této skupině vytvářejí objekty modelu stránky, které zahrnují DefaultHttpContextobjekty , ModelStateDictionary, ViewDataDictionary
ActionContext PageContext
a , a .PageContext
To je užitečné při provádění testů. Aplikace zpráv například naváže ModelState
chybu s AddModelError cílem zkontrolovat, jestli je při spuštění vrácena OnPostAddMessageAsync
platná PageResult 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ší materiály
- Testování částí V jazyce C# v .NET Core pomocí testu dotnet 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
- Začínáme s xUnit.net: Použití .NET Core s příkazovým řádkem sady .NET SDK
- Moq
- Rychlý start pro Moq
- JustMockLite: napodobování rozhraní pro vývojáře .NET. (Microsoft neudržuje ani nepodporuje.)