Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
ASP.NET Core támogatja a Pages-alkalmazások egységtesztjeit Razor . Az adatelérési réteg (DAL) és az oldalmodellek tesztelése a következőket biztosítja:
- A Pages-alkalmazások részei Razor egymástól függetlenül és egységként működnek az alkalmazásépítés során.
- Az osztályok és metódusok felelősségi köre korlátozott.
- További dokumentáció található az alkalmazás viselkedéséről.
- Az automatizált építés és üzembe helyezés során találhatók meg a kód frissítései által okozott regressziók.
Ez a témakör feltételezi, hogy alapszintű ismereteket szerezhet a Pages-alkalmazásokról és az Razor egységtesztekről. Ha nem ismeri a Pages-alkalmazásokat vagy a tesztelési Razor fogalmakat, tekintse meg az alábbi témaköröket:
- Razor A Pages architektúrája és fogalmai a ASP.NET Core-ban
- Oktatóanyag: Első lépések az Razor Oldalak az ASP.NET Core használatával
-
Tesztelés
dotnet test-val
Mintakód megtekintése vagy letöltése (hogyan töltsd le)
A mintaprojekt két alkalmazásból áll:
| App | Projektmappa | Description |
|---|---|---|
| Üzenetalkalmazás | src/RazorPagesTestSample | Lehetővé teszi a felhasználó számára, hogy üzenetet adjon hozzá, töröljön egy üzenetet, törölje az összes üzenetet, és elemezze az üzeneteket (az üzenetenkénti szavak átlagos számának megkeresése). |
| Alkalmazás tesztelése | tests/RazorPagesTestSample.Tests | Az üzenetalkalmazás DAL és Index oldalmodelljének egységtesztelésére szolgál. |
A tesztek egy IDE beépített tesztfunkcióival futtathatók, például Visual Studio. Ha Visual Studio Code-ot vagy parancssort használ, hajtsa végre a következő parancsot egy parancssorban a tests/RazorPagesTestSample.Tests mappában:
dotnet test
Üzenetalkalmazások szervezete
Az üzenetalkalmazás egy Razor Pages üzenetrendszer, amely a következő jellemzőkkel rendelkezik:
- Az alkalmazás indexoldala (
Pages/Index.cshtmlés ) egy felhasználói felületet ésPages/Index.cshtml.csoldalmodell-metódust biztosít az üzenetek hozzáadásának, törlésének és elemzésének szabályozásához (az üzenetenkénti szavak átlagos számának megkereséséhez). - Az üzeneteket a
Messageosztály (Data/Message.cs) írja le két tulajdonságokkal:Id(kulcs) ésText(üzenet). ATexttulajdonság megadása kötelező, és legfeljebb 200 karakter hosszúságú lehet. - Az üzenetek tárolása Entity Framework memórián belüli adatbázisának† használatával történik.
- Az alkalmazás tartalmaz egy DAL-t az adatbázis környezeti osztályában (
AppDbContextData/AppDbContext.cs). A DAL metódusok megjelölvevirtualvannak, ami lehetővé teszi a tesztekben való használathoz szükséges módszerek szimulálását. - Ha az adatbázis üres az alkalmazás indításakor, az üzenettároló három üzenettel lesz inicializálva. Ezeket a beszúrt üzeneteket a tesztekben is használják.
†Az EF-témakör, Az InMemorytesztelése című témakör bemutatja, hogyan használható memóriabeli adatbázis az MSTesttel végzett tesztekhez. Ez a témakör az xUnit tesztelési keretrendszert használja. A különböző tesztelési keretrendszerek tesztelési fogalmai és tesztelési implementációi hasonlóak, de nem azonosak.
Bár a mintaalkalmazás nem használja az adattármintát, és nem hatékony példa a Unit of Work (UoW) mintára, Razor a Pages támogatja ezeket a fejlesztési mintákat. További információ: Az infrastruktúra-adatmegőrzési réteg és atesztvezérlő logikájának tervezése a ASP.NET Core-ban (a minta implementálja az adattármintát).
Tesztalkalmazás szervezése
A tesztalkalmazás egy konzolalkalmazás a tests/RazorPagesTestSample.Tests mappában.
| Alkalmazásmappa tesztelése | Description |
|---|---|
| UnitTests |
|
| Utilities | Az adatbázis-környezet új beállításainak létrehozásához használt metódust TestDbContextOptions tartalmazza az egyes DAL-egységtesztekhez, hogy az adatbázis az egyes tesztek alapfeltételére térjen vissza. |
A tesztelési keretrendszer xUnit. Az objektum-mocking keretrendszer a Moq.
Az adatelérési réteg (DAL) egységtesztjei
Az üzenetalkalmazás egy DAL-val rendelkezik, amely négy metódust tartalmaz az AppDbContext osztályban (src/RazorPagesTestSample/Data/AppDbContext.cs). Minden metódus egy vagy két egységteszttel rendelkezik a tesztalkalmazásban.
| DAL metódus | Function |
|---|---|
GetMessagesAsync |
Adatbázisból beolvas egy List<Message>-t, amely a Text tulajdonság szerint van rendezve. |
AddMessageAsync |
Hozzáad egy újat Message az adatbázishoz. |
DeleteAllMessagesAsync |
Törli az adatbázis összes Message bejegyzését. |
DeleteMessageAsync |
Egyetlen adat Message törlése az adatbázisból a következő szerint Id: . |
A DAL egységtesztjeihez minden teszthez szükség van egy új DbContextOptions létrehozására AppDbContext használatával. Egy megközelítés az DbContextOptions létrehozásához az, hogy minden tesztnél egy DbContextOptionsBuilder-t használunk.
var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("InMemoryDb");
using (var db = new AppDbContext(optionsBuilder.Options))
{
// Use the db here in the unit test.
}
Ezzel a megközelítéssel az a probléma, hogy minden teszt az adatbázist abban az állapotban kapja meg, ahogyan az előző teszt hagyta. Ez problémás lehet, ha olyan atomi egységteszteket próbál meg írni, amelyek nem zavarják egymást. Ha azt szeretné, hogy minden AppDbContext teszt külön adatbáziskörnyezetet használjon, adjon meg egy új szolgáltatón alapuló DbContextOptions példányt. A tesztalkalmazás bemutatja, hogyan teheti ezt meg az osztálymetódusával UtilitiesTestDbContextOptions (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 A DAL egységtesztjeinek használatával minden teszt atomi módon futtatható egy friss adatbázispéldánysal:
using (var db = new AppDbContext(Utilities.TestDbContextOptions()))
{
// Use the db here in the unit test.
}
Az osztály DataAccessLayerTestUnitTests/DataAccessLayerTest.cs minden tesztmódszere hasonló elrendezés-végrehajtás-igazolás mintát követ.
- Elrendezés: Az adatbázis a teszthez van konfigurálva, és/vagy a várt eredmény van meghatározva.
- Művelet: A teszt végrehajtása.
- Állítások: Az állításokat azért tesszük, hogy megállapítsuk, a teszt eredménye sikeres-e.
A DeleteMessageAsync metódus például felelős egyetlen, a Id által azonosított src/RazorPagesTestSample/Data/AppDbContext.cs üzenet eltávolításáért.
public async virtual Task DeleteMessageAsync(int id)
{
var message = await Messages.FindAsync(id);
if (message != null)
{
Messages.Remove(message);
await SaveChangesAsync();
}
}
Ehhez a módszerhez két teszt van. Az egyik teszt ellenőrzi, hogy a metódus töröl-e egy üzenetet, ha az üzenet megtalálható az adatbázisban. A másik módszer azt ellenőrzi, hogy az adatbázis nem változik-e, ha a törlési üzenet Id nem létezik. A DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFound módszer az alábbiakban látható:
[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));
}
}
Először a metódus végrehajtja az Elrendezés lépést, ahol az Act lépés előkészítése történik. A kiinduló üzeneteket a rendszer lekérte és megtartotta seedMessages. A rendszer menti a bejuttatási üzeneteket az adatbázisba. Az üzenet Id1 törlésre van beállítva. A DeleteMessageAsync metódus végrehajtásakor a várt üzeneteknek meg kell kapniuk az összes üzenetet, kivéve azt, amelyiknek Id értéke 1. A expectedMessages változó ezt a várt eredményt jelöli.
// Arrange
var seedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(seedMessages);
await db.SaveChangesAsync();
var recId = 1;
var expectedMessages =
seedMessages.Where(message => message.Id != recId).ToList();
A metódus működése: A DeleteMessageAsync metódust úgy hajtják végre, hogy a recId-t a 1-be adják át.
// Act
await db.DeleteMessageAsync(recId);
Végül a metódus kinyeri a Messages-t a kontextusból, és összehasonlítja a expectedMessages-el, igazolva, hogy a kettő egyenlő.
// 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));
Ahhoz, hogy összehasonlíthassuk, a kettő List<Message> megegyezik:
- Az üzeneteket a rendszer a következő szerint rendezi
Id: . - Az üzenetpárok a tulajdonságon
Textvannak összehasonlítva.
Egy hasonló tesztmetódus ellenőrzi a DeleteMessageAsync_NoMessageIsDeleted_WhenMessageIsNotFound nem létező üzenetek törlésének eredményét. Ebben az esetben az adatbázis várt üzeneteinek meg kell egyeznie a metódus végrehajtása utáni DeleteMessageAsync tényleges üzenetel. Az adatbázis tartalmában nem lehet változás:
[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));
}
}
Az oldalmodell módszereinek egységtesztjei
Az egységtesztek egy másik készlete felelős az oldalmodell-módszerek teszteléséért. Az üzenetalkalmazás indexlapmodelljei a IndexModel következő osztályban src/RazorPagesTestSample/Pages/Index.cshtml.cstalálhatók: .
| Oldalmodell módszer | Function |
|---|---|
OnGetAsync |
A GetMessagesAsync metódust használva szerzi meg a felhasználói felülethez tartozó DAL-üzeneteket. |
OnPostAddMessageAsync |
Ha a ModelState érvényes, meghívja AddMessageAsync , hogy adjon hozzá egy üzenetet az adatbázishoz. |
OnPostDeleteAllMessagesAsync |
Az adatbázis összes üzenetének törlését kéri DeleteAllMessagesAsync . |
OnPostDeleteMessageAsync |
Végrehajtja DeleteMessageAsync a megadott üzenet Id törlését. |
OnPostAnalyzeMessagesAsync |
Ha egy vagy több üzenet szerepel az adatbázisban, az üzenetenkénti szavak átlagos számát számítja ki. |
Az oldalmodell módszereit hét teszttel teszteljük az IndexPageTests osztályban (tests/RazorPagesTestSample.Tests/UnitTests/IndexPageTests.cs). A tesztek az ismerős Elrendezés-Cselekvés-Kijelentés mintát használják. Ezek a tesztek a következőkre összpontosítanak:
- Annak meghatározása, hogy a metódusok a helyes viselkedést követik-e, ha a ModelState érvénytelen.
- A metódusok megerősítése a helyes IActionResulteredményt hozza létre.
- Annak ellenőrzése, hogy a tulajdonságérték-hozzárendelések megfelelően lettek-e elvégezve.
Ez a tesztcsoport gyakran szimulálja a DAL metódusait a várt adatok előállításához az Act lépéshez, ahol egy oldalmodell metódusát hajtják végre. A GetMessagesAsyncAppDbContext metódusa például szimulálva van a kimenet előállítására. Amikor egy oldalmodell-metódus végrehajtja ezt a metódust, a modell visszaadja az eredményt. Az adatok nem az adatbázisból származnak. Ez kiszámítható, megbízható tesztelési feltételeket hoz létre a DAL oldalmodell-tesztekben való használatához.
A OnGetAsync_PopulatesThePageModel_WithAListOfMessages teszt azt mutatja be, hogy a GetMessagesAsync függvény hogyan van mock-olva az oldalmodell számára.
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);
Amikor a OnGetAsync metódus végrehajtása az Act lépésben történik, meghívja az oldalmodell metódusát GetMessagesAsync .
Egységteszt cselekvési lépés (tests/RazorPagesTestSample.Tests/UnitTests/IndexPageTests.cs):
// Act
await pageModel.OnGetAsync();
IndexPage az oldalmodell metódusa OnGetAsync (src/RazorPagesTestSample/Pages/Index.cshtml.cs):
public async Task OnGetAsync()
{
Messages = await _db.GetMessagesAsync();
}
A GetMessagesAsync DAL metódusa nem adja vissza a metódushívás eredményét. A metódus szimulált verziója visszaadja az eredményt.
Ebben a Assert lépésben a tényleges üzenetek (actualMessages) az oldalmodell Messages tulajdonságából vannak hozzárendelve. Az üzenetek hozzárendelésekor a rendszer típusellenőrzést is végez. A várt és a tényleges üzenetek Text tulajdonságait hasonlítják össze. A teszt azt állítja, hogy a két List<Message> példány ugyanazokat az üzeneteket tartalmazza.
// 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));
A csoport többi tesztje olyan lapmodell-objektumokat hoz létre, amelyek tartalmazzák a DefaultHttpContext, a ModelStateDictionary, egy ActionContext a PageContext felállításához, egy ViewDataDictionary-t és egy PageContext-t. Ezek hasznosak a tesztek elvégzéséhez. Például az üzenet alkalmazás ModelState hibát állapít meg AddModelError annak ellenőrzésére, hogy PageResult végrehajtásakor érvényes OnPostAddMessageAsync kerüljön visszaadásra.
[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);
}
További erőforrások
ASP.NET Core támogatja a Pages-alkalmazások egységtesztjeit Razor . Az adatelérési réteg (DAL) és az oldalmodellek tesztelése a következőket biztosítja:
- A Pages-alkalmazások részei Razor egymástól függetlenül és egységként működnek az alkalmazásépítés során.
- Az osztályok és metódusok felelősségi köre korlátozott.
- További dokumentáció található az alkalmazás viselkedéséről.
- Az automatizált építés és üzembe helyezés során találhatók meg a kód frissítései által okozott regressziók.
Ez a témakör feltételezi, hogy alapszintű ismereteket szerezhet a Pages-alkalmazásokról és az Razor egységtesztekről. Ha nem ismeri a Pages-alkalmazásokat vagy a tesztelési Razor fogalmakat, tekintse meg az alábbi témaköröket:
- Razor A Pages architektúrája és fogalmai a ASP.NET Core-ban
- Oktatóanyag: Első lépések az Razor Oldalak az ASP.NET Core használatával
-
Tesztelés
dotnet test-val
Mintakód megtekintése vagy letöltése (hogyan töltsd le)
A mintaprojekt két alkalmazásból áll:
| App | Projektmappa | Description |
|---|---|---|
| Üzenetalkalmazás | src/RazorPagesTestSample | Lehetővé teszi a felhasználó számára, hogy üzenetet adjon hozzá, töröljön egy üzenetet, törölje az összes üzenetet, és elemezze az üzeneteket (az üzenetenkénti szavak átlagos számának megkeresése). |
| Alkalmazás tesztelése | tests/RazorPagesTestSample.Tests | Az üzenetalkalmazás DAL és Index oldalmodelljének egységtesztelésére szolgál. |
A tesztek egy IDE beépített tesztfunkcióival futtathatók, például Visual Studio. Ha Visual Studio Code-ot vagy parancssort használ, hajtsa végre a következő parancsot egy parancssorban a tests/RazorPagesTestSample.Tests mappában:
dotnet test
Üzenetalkalmazások szervezete
Az üzenetalkalmazás egy Razor Pages üzenetrendszer, amely a következő jellemzőkkel rendelkezik:
- Az alkalmazás indexoldala (
Pages/Index.cshtmlés ) egy felhasználói felületet ésPages/Index.cshtml.csoldalmodell-metódust biztosít az üzenetek hozzáadásának, törlésének és elemzésének szabályozásához (az üzenetenkénti szavak átlagos számának megkereséséhez). - Az üzeneteket a
Messageosztály (Data/Message.cs) írja le két tulajdonságokkal:Id(kulcs) ésText(üzenet). ATexttulajdonság megadása kötelező, és legfeljebb 200 karakter hosszúságú lehet. - Az üzenetek tárolása Entity Framework memórián belüli adatbázisának† használatával történik.
- Az alkalmazás tartalmaz egy DAL-t az adatbázis környezeti osztályában (
AppDbContextData/AppDbContext.cs). A DAL metódusok megjelölvevirtualvannak, ami lehetővé teszi a tesztekben való használathoz szükséges módszerek szimulálását. - Ha az adatbázis üres az alkalmazás indításakor, az üzenettároló három üzenettel lesz inicializálva. Ezeket a beszúrt üzeneteket a tesztekben is használják.
†Az EF-témakör, Az InMemorytesztelése című témakör bemutatja, hogyan használható memóriabeli adatbázis az MSTesttel végzett tesztekhez. Ez a témakör az xUnit tesztelési keretrendszert használja. A különböző tesztelési keretrendszerek tesztelési fogalmai és tesztelési implementációi hasonlóak, de nem azonosak.
Bár a mintaalkalmazás nem használja az adattármintát, és nem hatékony példa a Unit of Work (UoW) mintára, Razor a Pages támogatja ezeket a fejlesztési mintákat. További információ: Az infrastruktúra-adatmegőrzési réteg és atesztvezérlő logikájának tervezése a ASP.NET Core-ban (a minta implementálja az adattármintát).
Tesztalkalmazás szervezése
A tesztalkalmazás egy konzolalkalmazás a tests/RazorPagesTestSample.Tests mappában.
| Alkalmazásmappa tesztelése | Description |
|---|---|
| UnitTests |
|
| Utilities | Az adatbázis-környezet új beállításainak létrehozásához használt metódust TestDbContextOptions tartalmazza az egyes DAL-egységtesztekhez, hogy az adatbázis az egyes tesztek alapfeltételére térjen vissza. |
A tesztelési keretrendszer xUnit. Az objektum-mocking keretrendszer a Moq.
Az adatelérési réteg (DAL) egységtesztjei
Az üzenetalkalmazás egy DAL-val rendelkezik, amely négy metódust tartalmaz az AppDbContext osztályban (src/RazorPagesTestSample/Data/AppDbContext.cs). Minden metódus egy vagy két egységteszttel rendelkezik a tesztalkalmazásban.
| DAL metódus | Function |
|---|---|
GetMessagesAsync |
Adatbázisból beolvas egy List<Message>-t, amely a Text tulajdonság szerint van rendezve. |
AddMessageAsync |
Hozzáad egy újat Message az adatbázishoz. |
DeleteAllMessagesAsync |
Törli az adatbázis összes Message bejegyzését. |
DeleteMessageAsync |
Egyetlen adat Message törlése az adatbázisból a következő szerint Id: . |
A DAL egységtesztjeihez minden teszthez szükség van egy új DbContextOptions létrehozására AppDbContext használatával. Egy megközelítés az DbContextOptions létrehozásához az, hogy minden tesztnél egy DbContextOptionsBuilder-t használunk.
var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("InMemoryDb");
using (var db = new AppDbContext(optionsBuilder.Options))
{
// Use the db here in the unit test.
}
Ezzel a megközelítéssel az a probléma, hogy minden teszt az adatbázist abban az állapotban kapja meg, ahogyan az előző teszt hagyta. Ez problémás lehet, ha olyan atomi egységteszteket próbál meg írni, amelyek nem zavarják egymást. Ha azt szeretné, hogy minden AppDbContext teszt külön adatbáziskörnyezetet használjon, adjon meg egy új szolgáltatón alapuló DbContextOptions példányt. A tesztalkalmazás bemutatja, hogyan teheti ezt meg az osztálymetódusával UtilitiesTestDbContextOptions (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 A DAL egységtesztjeinek használatával minden teszt atomi módon futtatható egy friss adatbázispéldánysal:
using (var db = new AppDbContext(Utilities.TestDbContextOptions()))
{
// Use the db here in the unit test.
}
Az osztály DataAccessLayerTestUnitTests/DataAccessLayerTest.cs minden tesztmódszere hasonló elrendezés-végrehajtás-igazolás mintát követ.
- Elrendezés: Az adatbázis a teszthez van konfigurálva, és/vagy a várt eredmény van meghatározva.
- Művelet: A teszt végrehajtása.
- Állítások: Az állításokat azért tesszük, hogy megállapítsuk, a teszt eredménye sikeres-e.
A DeleteMessageAsync metódus például felelős egyetlen, a Id által azonosított src/RazorPagesTestSample/Data/AppDbContext.cs üzenet eltávolításáért.
public async virtual Task DeleteMessageAsync(int id)
{
var message = await Messages.FindAsync(id);
if (message != null)
{
Messages.Remove(message);
await SaveChangesAsync();
}
}
Ehhez a módszerhez két teszt van. Az egyik teszt ellenőrzi, hogy a metódus töröl-e egy üzenetet, ha az üzenet megtalálható az adatbázisban. A másik módszer azt ellenőrzi, hogy az adatbázis nem változik-e, ha a törlési üzenet Id nem létezik. A DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFound módszer az alábbiakban látható:
[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));
}
}
Először a metódus végrehajtja az Elrendezés lépést, ahol az Act lépés előkészítése történik. A kiinduló üzeneteket a rendszer lekérte és megtartotta seedMessages. A rendszer menti a bejuttatási üzeneteket az adatbázisba. Az üzenet Id1 törlésre van beállítva. A DeleteMessageAsync metódus végrehajtásakor a várt üzeneteknek meg kell kapniuk az összes üzenetet, kivéve azt, amelyiknek Id értéke 1. A expectedMessages változó ezt a várt eredményt jelöli.
// Arrange
var seedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(seedMessages);
await db.SaveChangesAsync();
var recId = 1;
var expectedMessages =
seedMessages.Where(message => message.Id != recId).ToList();
A metódus működése: A DeleteMessageAsync metódust úgy hajtják végre, hogy a recId-t a 1-be adják át.
// Act
await db.DeleteMessageAsync(recId);
Végül a metódus kinyeri a Messages-t a kontextusból, és összehasonlítja a expectedMessages-el, igazolva, hogy a kettő egyenlő.
// 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));
Ahhoz, hogy összehasonlíthassuk, a kettő List<Message> megegyezik:
- Az üzeneteket a rendszer a következő szerint rendezi
Id: . - Az üzenetpárok a tulajdonságon
Textvannak összehasonlítva.
Egy hasonló tesztmetódus ellenőrzi a DeleteMessageAsync_NoMessageIsDeleted_WhenMessageIsNotFound nem létező üzenetek törlésének eredményét. Ebben az esetben az adatbázis várt üzeneteinek meg kell egyeznie a metódus végrehajtása utáni DeleteMessageAsync tényleges üzenetel. Az adatbázis tartalmában nem lehet változás:
[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));
}
}
Az oldalmodell módszereinek egységtesztjei
Az egységtesztek egy másik készlete felelős az oldalmodell-módszerek teszteléséért. Az üzenetalkalmazás indexlapmodelljei a IndexModel következő osztályban src/RazorPagesTestSample/Pages/Index.cshtml.cstalálhatók: .
| Oldalmodell módszer | Function |
|---|---|
OnGetAsync |
A GetMessagesAsync metódust használva szerzi meg a felhasználói felülethez tartozó DAL-üzeneteket. |
OnPostAddMessageAsync |
Ha a ModelState érvényes, meghívja AddMessageAsync , hogy adjon hozzá egy üzenetet az adatbázishoz. |
OnPostDeleteAllMessagesAsync |
Az adatbázis összes üzenetének törlését kéri DeleteAllMessagesAsync . |
OnPostDeleteMessageAsync |
Végrehajtja DeleteMessageAsync a megadott üzenet Id törlését. |
OnPostAnalyzeMessagesAsync |
Ha egy vagy több üzenet szerepel az adatbázisban, az üzenetenkénti szavak átlagos számát számítja ki. |
Az oldalmodell módszereit hét teszttel teszteljük az IndexPageTests osztályban (tests/RazorPagesTestSample.Tests/UnitTests/IndexPageTests.cs). A tesztek az ismerős Elrendezés-Cselekvés-Kijelentés mintát használják. Ezek a tesztek a következőkre összpontosítanak:
- Annak meghatározása, hogy a metódusok a helyes viselkedést követik-e, ha a ModelState érvénytelen.
- A metódusok megerősítése a helyes IActionResulteredményt hozza létre.
- Annak ellenőrzése, hogy a tulajdonságérték-hozzárendelések megfelelően lettek-e elvégezve.
Ez a tesztcsoport gyakran szimulálja a DAL metódusait a várt adatok előállításához az Act lépéshez, ahol egy oldalmodell metódusát hajtják végre. A GetMessagesAsyncAppDbContext metódusa például szimulálva van a kimenet előállítására. Amikor egy oldalmodell-metódus végrehajtja ezt a metódust, a modell visszaadja az eredményt. Az adatok nem az adatbázisból származnak. Ez kiszámítható, megbízható tesztelési feltételeket hoz létre a DAL oldalmodell-tesztekben való használatához.
A OnGetAsync_PopulatesThePageModel_WithAListOfMessages teszt azt mutatja be, hogy a GetMessagesAsync függvény hogyan van mock-olva az oldalmodell számára.
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);
Amikor a OnGetAsync metódus végrehajtása az Act lépésben történik, meghívja az oldalmodell metódusát GetMessagesAsync .
Egységteszt cselekvési lépés (tests/RazorPagesTestSample.Tests/UnitTests/IndexPageTests.cs):
// Act
await pageModel.OnGetAsync();
IndexPage az oldalmodell metódusa OnGetAsync (src/RazorPagesTestSample/Pages/Index.cshtml.cs):
public async Task OnGetAsync()
{
Messages = await _db.GetMessagesAsync();
}
A GetMessagesAsync DAL metódusa nem adja vissza a metódushívás eredményét. A metódus szimulált verziója visszaadja az eredményt.
Ebben a Assert lépésben a tényleges üzenetek (actualMessages) az oldalmodell Messages tulajdonságából vannak hozzárendelve. Az üzenetek hozzárendelésekor a rendszer típusellenőrzést is végez. A várt és a tényleges üzenetek Text tulajdonságait hasonlítják össze. A teszt azt állítja, hogy a két List<Message> példány ugyanazokat az üzeneteket tartalmazza.
// 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));
A csoport többi tesztje olyan lapmodell-objektumokat hoz létre, amelyek tartalmazzák a DefaultHttpContext, a ModelStateDictionary, egy ActionContext a PageContext felállításához, egy ViewDataDictionary-t és egy PageContext-t. Ezek hasznosak a tesztek elvégzéséhez. Például az üzenet alkalmazás ModelState hibát állapít meg AddModelError annak ellenőrzésére, hogy PageResult végrehajtásakor érvényes OnPostAddMessageAsync kerüljön visszaadásra.
[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);
}
További erőforrások
-
Tesztelés
dotnet test-val - Tesztvezérlő logika az ASP.NET Core-ban
- Egységtesztelje a kódját (Visual Studio)
- Az integrációs tesztek az ASP.NET Core-ban
- xUnit.net
- Bevezetés az xUnit.net-be
- Moq
- Rövid útmutató a Moq-hez
- JustMockLite: Egy csúfoló keretrendszer .NET-fejlesztők számára. (A Microsoft nem tartja karban vagy nem támogatja.)