RazorASP.NET Core birim testleri sayfa testleri
ASP.NET Core, sayfaların uygulamalarının birim testlerini destekler Razor . Veri erişim katmanı (DAL) ve sayfa modellerinin testleri şunları sağlamaya yardımcı olur:
- Bir Razor Sayfalar uygulamasının parçaları, uygulama oluşturma sırasında bağımsız olarak ve bir birim olarak birlikte çalışır.
- Sınıfların ve yöntemlerin sınırlı sorumluluk kapsamları vardır.
- Uygulamanın nasıl davranması ile ilgili ek belgeler vardır.
- Kod güncelleştirmeleri tarafından ilgili hatalar olan gerileme, otomatik derleme ve dağıtım sırasında bulunur.
Bu konu başlığı altında, Razor uygulamalar ve birim testleri için temel olarak anlaşıldığınız varsayılmaktadır. RazorSayfalarla ilgili uygulamalar veya test kavramları hakkında bilgi sahibi değilseniz aşağıdaki konulara bakın:
- RazorASP.NET Core'de Sayfalara Giriş
- Öğretici: Kullanmaya başlayın Razor Sayfaları ile ASP.NET Core
- DotNet test ve xUnit kullanarak .NET Core 'Da birim testi C#
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)
Örnek proje iki uygulamalardan oluşur:
| Uygulama | Project klasörü | Description |
|---|---|---|
| İleti uygulaması | src/ Razor pagestestsample | Kullanıcının ileti eklemesine, bir ileti silmesine, tüm iletileri silmesine ve iletileri çözümlemesine (ileti başına ortalama sözcük sayısını bulur) izin verir. |
| Test uygulaması | testler/ Razor pagestestsample. testler | İleti uygulamasının DAL ve Dizin sayfa modelini test etmek için kullanılır. |
testler, Visual Studio veya Mac için Visual Studiogibi bir ıde 'nin yerleşik test özellikleri kullanılarak çalıştırılabilir. Visual Studio Code veya komut satırı kullanıyorsanız, testler/ Razor pagestestsample. tests klasöründeki bir komut isteminde aşağıdaki komutu yürütün:
dotnet test
İleti uygulama organizasyonu
İleti uygulaması, Razor aşağıdaki özelliklere sahip bir sayfalar ileti sistemidir:
- Uygulamanın (Pages/Index. cshtml ve Pages/index. cshtml. cs) dizin sayfası, iletilerin eklenmesi, silinmesini ve ANALIZINI denetlemek için bir UI ve sayfa modeli yöntemleri sağlar (ileti başına ortalama sözcük sayısını bulur).
- Bir ileti,
Messagesınıfı (Data/Message. cs) ile iki özelliği olan (Idanahtar) veText(ileti) açıklanmaktadır.TextÖzelliği gereklidir ve 200 karakterle sınırlıdır. - İletiler, Entity Framework bellek içi veritabanı† kullanılarak depolanır.
- Uygulama, veritabanı bağlamı sınıfında
AppDbContext(Data/AppDbContext. cs) bir dal içerir. DAL Yöntemleri işaretlenirvirtualve bu yöntemler, testlerde kullanım için izin verir. - Veritabanı uygulama başlangıcında boşsa, ileti deposu üç iletiyle başlatılır. Bu sağlanan iletiler , testlerde de kullanılır.
EF konusunda, InMemory Ile Test†, MSTest ile testler için bellek içi bir veritabanının nasıl kullanılacağını açıklar. Bu konu xUnit test çerçevesini kullanır. Farklı test çerçeveleri genelinde test kavramları ve test uygulamaları benzerdir ancak aynı değildir.
Örnek uygulama depo desenini kullanmaz ve Iş birimi (UoW) düzenininetkin bir örneği olmamasına karşın, Razor Sayfalar bu geliştirme düzenlerini destekler. Daha fazla bilgi için bkz. altyapı Kalıcılık katmanını tasarlama ve ASP.NET Core 'de test denetleyicisi mantığı (örnek depo modelini uygular).
Test uygulaması kuruluşu
Test uygulaması, testler/ Razor pagestestsample. Tests klasörünün içindeki bir konsol uygulamasıdır.
| Test uygulaması klasörü | Description |
|---|---|
| UnitTests |
|
| Yardımcı Programlar | Her bir TestDbContextOptions dal birim testi için yeni veritabanı bağlamı seçenekleri oluşturmak için kullanılan yöntemi içerir, böylece veritabanı her test için kendi temel koşuluna sıfırlanır. |
Test çerçevesi xUnit' dir. Nesne sahte işlem çerçevesi moqolur.
Veri erişim katmanının birim testleri (DAL)
İleti uygulamasında, sınıfında dört yöntem bulunan bir DAL vardır AppDbContext (src/ Razor Pagestestsample/Data/appdbcontext. cs). Her yöntemin test uygulamasında bir veya iki birim testi vardır.
| DAL yöntemi | İşlev |
|---|---|
GetMessagesAsync |
List<Message>Özelliği tarafından sıralanan veritabanından bir alır Text . |
AddMessageAsync |
Veritabanına bir ekler Message . |
DeleteAllMessagesAsync |
Tüm Message girdileri veritabanından siler. |
DeleteMessageAsync |
Veritabanından tek tek siler Message Id . |
DAL birim testleri DbContextOptions her bir test için yeni bir oluşturma AppDbContext için gereklidir. Her test için öğesini oluşturmaya yönelik bir yaklaşım, şunu DbContextOptions kullanmaktır DbContextOptionsBuilder :
var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("InMemoryDb");
using (var db = new AppDbContext(optionsBuilder.Options))
{
// Use the db here in the unit test.
}
Bu yaklaşımla ilgili sorun, her testin, önceki testin bulunduğu herhangi bir durumda veritabanını aldığından emin olur. Bu, birbirleriyle karışmaz atomik birim testleri yazmaya çalışırken sorunlu olabilir. AppDbContextHer test için yeni bir veritabanı bağlamı kullanmaya zorlamak için, DbContextOptions Yeni bir hizmet sağlayıcısına dayalı bir örnek sağlayın. Test uygulaması, sınıfının sınıf yöntemi kullanılarak nasıl yapılacağını gösterir Utilities TestDbContextOptions (testler/ Razor Pagestestsample. testler/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;
}
DbContextOptionsDal birim testlerinde kullanılması, her testin yeni bir veritabanı örneğiyle otomatik olarak çalıştırılmasına izin verir:
using (var db = new AppDbContext(Utilities.TestDbContextOptions()))
{
// Use the db here in the unit test.
}
Sınıftaki her bir test yöntemi DataAccessLayerTest (unittests/DataAccessLayerTest. cs) benzer bir düzenleme-işlem onaylama düzeni izler:
- Düzenle: veritabanı test için yapılandırılmış ve/veya beklenen sonuç tanımlandı.
- Davran: test yürütülür.
- Onaylama: test sonucunun başarılı olup olmadığını belirleme onayları yapılır.
Örneğin, DeleteMessageAsync yöntemi Id (src/ Razor Pagestestsample/Data/appdbcontext. cs) tarafından tanımlanan tek bir iletinin kaldırılmasından sorumludur:
public async virtual Task DeleteMessageAsync(int id)
{
var message = await Messages.FindAsync(id);
if (message != null)
{
Messages.Remove(message);
await SaveChangesAsync();
}
}
Bu yöntem için iki test vardır. Bir test, bir ileti veritabanında olduğunda yöntemin bir iletiyi sildiğini denetler. Diğer yöntem, silme iletisi yoksa veritabanının değişmediğini sınar Id . DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFoundYöntemi aşağıda gösterilmiştir:
[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));
}
}
İlk olarak, yöntemi, hareket adımının hazırlanması gereken düzenleme adımını gerçekleştirir. Dengeli dağıtım iletileri ' de alınır ve tutulur seedMessages . Dengeli dağıtım iletileri veritabanına kaydedilir. İçeren ileti Id 1 silinmek üzere ayarlanmış. DeleteMessageAsyncYöntemi yürütüldüğünde, beklenen iletilerde, ' ın dışında bir ileti olmalıdır Id 1 . expectedMessagesDeğişken, beklenen bu sonucu temsil eder.
// Arrange
var seedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(seedMessages);
await db.SaveChangesAsync();
var recId = 1;
var expectedMessages =
seedMessages.Where(message => message.Id != recId).ToList();
Yöntemi şu şekilde davranır: DeleteMessageAsync yöntemi ' ın içinde geçirme yürütülür recId 1 :
// Act
await db.DeleteMessageAsync(recId);
Son olarak, yöntemi bağlamını edinir Messages ve expectedMessages iki eşit olan asserile karşılaştırır:
// 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));
İki ikisinin de aynı olduğunu karşılaştırmak için List<Message> :
- İletiler tarafından sıralanır
Id. - İleti çiftleri özelliği ile karşılaştırılır
Text.
Benzer bir test yöntemi, DeleteMessageAsync_NoMessageIsDeleted_WhenMessageIsNotFound mevcut olmayan bir iletiyi silmeye çalışılması sonucunu denetler. Bu durumda, veritabanındaki beklenen iletiler, yöntem yürütüldükten sonra gerçek iletilere eşit olmalıdır DeleteMessageAsync . Veritabanının içeriğinde değişiklik olmamalıdır:
[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));
}
}
Sayfa modeli yöntemlerinin birim testleri
Başka bir birim testi kümesi, sayfa modeli yöntemlerinin sınamalarından sorumludur. İleti uygulamasında Dizin sayfası modelleri IndexModel src/ Razor pagestestsample/Pages/Index. cshtml. cs içindeki sınıfta bulunur.
| Sayfa modeli yöntemi | İşlev |
|---|---|
OnGetAsync |
Yöntemini kullanarak, Kullanıcı arabirimi için DAL öğesinden gelen iletileri alır GetMessagesAsync . |
OnPostAddMessageAsync |
ModelState geçerliyse, AddMessageAsync veritabanına bir ileti eklemek için çağırır. |
OnPostDeleteAllMessagesAsync |
DeleteAllMessagesAsyncVeritabanındaki tüm iletileri silmek için çağırır. |
OnPostDeleteMessageAsync |
DeleteMessageAsyncBelirtilen bir iletiyi silmek için yürütülür Id . |
OnPostAnalyzeMessagesAsync |
Veritabanında bir veya daha fazla ileti varsa, ileti başına ortalama sözcük sayısını hesaplar. |
Sayfa modeli yöntemleri sınıfında yedi test kullanılarak test edilir IndexPageTests (tests/ Razor PagesTestSample.Tests/UnitTests/IndexPageTests.cs). Testler tanıdık Arrange-Assert-Act desenini kullanır. Bu testler şu testlere odaklanır:
- ModelState geçersiz olduğunda yöntemlerin doğru davranışa uygun olup olmadığını belirleme.
- Yöntemlerin doğru olduğunu IActionResult onaylama.
- Özellik değeri atamaları doğru şekilde denetlendi.
Bu test grubu genellikle sayfa modeli yönteminin yürütüleceği Act adımı için beklenen verileri üretmek için DAL yöntemlerini taklit eder. Örneğin, GetMessagesAsync yönteminin AppDbContext çıkışı üretmek için sahtedir. Bir sayfa modeli yöntemi bu yöntemi yürütürken sahte sonuç döndürür. Veriler veritabanından değildir. Bu, dal'ı sayfa modeli testlerinde kullanmak için tahmin edilebilir, güvenilir test koşulları oluşturur.
Test, OnGetAsync_PopulatesThePageModel_WithAListOfMessages yöntemin GetMessagesAsync sayfa modeli için nasıl sahte olduğunu gösterir:
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);
Yöntemi OnGetAsync Act adımını yürüttük, sayfa modelinin yöntemini GetMessagesAsync çağıran.
Birim testi Eylemi adımı (tests/ Razor PagesTestSample.Tests/UnitTests/IndexPageTests.cs):
// Act
await pageModel.OnGetAsync();
IndexPagesayfa modelinin yöntemi OnGetAsync (src/ Razor PagesTestSample/Pages/Index.cshtml.cs):
public async Task OnGetAsync()
{
Messages = await _db.GetMessagesAsync();
}
GetMessagesAsyncDAL'daki yöntemi, bu yöntem çağrısının sonucu dönmez. yönteminin sahte sürümü sonucu döndürür.
Adımda, Assert gerçek iletiler ( ) sayfa modelinin actualMessages Messages özelliğinden atanır. İletiler atandığı zaman da tür denetimi gerçekleştirilir. Beklenen ve gerçek iletiler özellikleriyle Text karşılaştırıldı. Test, iki örneğin aynı List<Message> iletileri içerdiğini onaylar.
// 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));
Bu gruptaki diğer testler , , ve oluşturmak için , , ve içeren DefaultHttpContext ModelStateDictionary sayfa modeli nesneleri ActionContext PageContext ViewDataDictionary PageContext oluşturur. Bunlar testleri yürütmek için yararlıdır. Örneğin, ileti uygulaması yürütülürken geçerli bir döndürül olup olmadığını ModelState kontrol etmek için ile bir hata AddModelError PageResult OnPostAddMessageAsync verir:
[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);
}
Ek kaynaklar
- Dotnet test ve xUnit kullanarak .NET Core'da C# birim testi
- ASP.NET Core 'de test denetleyicisi mantığı
- Kodunuzu Birim Testi (Visual Studio)
- ASP.NET Core tümleştirme testleri
- xUnit.net
- Mac için Visual Studio kullanarak macOS’ta eksiksiz bir .NET Core çözümü derleme
- xUnit.net kullanmaya başlama: .NET CORE'ı .NET SDK komut satırıyla kullanma
- Moq
- Moq Hızlı Başlangıç
ASP.NET Core, Sayfalar uygulamalarının birim Razor testlerini destekler. Veri erişim katmanı (DAL) ve sayfa modellerinin testleri şunların sağlanmasına yardımcı olur:
- Bir Pages uygulamasının Razor parçaları, uygulamanın yapısı sırasında bağımsız olarak ve bir birim olarak birlikte çalışır.
- Sınıflar ve yöntemler sınırlı sorumluluk kapsamları içerir.
- Uygulamanın nasıl davranması gerektiğine ilişkin ek belgeler mevcuttur.
- Kodda yapılan güncelleştirmelerin getirdiği hatalar olan regresyonlar, otomatik bina ve dağıtım sırasında bulunur.
Bu konu, Sayfalar uygulamaları ve birim testleri hakkında temel Razor bir anlayışa sahip olduğunu varsayıyor. Sayfalar uygulamaları veya test kavramları hakkında bilgim yoksa Razor aşağıdaki konulara bakın:
- RazorASP.NET Core'de Sayfalara Giriş
- Öğretici: Kullanmaya başlayın Razor Sayfaları ile ASP.NET Core
- Dotnet test ve xUnit kullanarak .NET Core'da C# birim testi
Örnek kodu görüntüleme veya indirme ( nasılindir)
Örnek proje iki uygulamalardan oluşur:
| Uygulama | Project klasörü | Description |
|---|---|---|
| İleti uygulaması | src/ Razor PagesTestSample | Kullanıcının ileti ekleme, bir iletiyi silme, tüm iletileri silme ve iletileri analiz etme (ileti başına ortalama sözcük sayısını bulma) olanak sağlar. |
| Uygulamayı test edin | tests/ Razor PagesTestSample.Tests | İleti uygulamasının DAL ve Dizin sayfa modelini birim testi için kullanılır. |
Testler, IDE'nin IDE'nin Visual Studio veya Mac için Visual Studio. Visual Studio Code veya komut satırı kullanıyorsanız, tests/ Razor PagesTestSample.Tests klasöründeki bir komut isteminde aşağıdaki komutu yürütün:
dotnet test
İleti uygulaması kuruluşu
İleti uygulaması, aşağıdaki Razor özelliklere sahip bir Sayfalar ileti sistemidir:
- Uygulamanın Dizin sayfası (Pages/Index.cshtml ve Pages/Index.cshtml.cs), iletilerin toplama, silme ve analiz işlemlerini denetlemeye (ileti başına ortalama sözcük sayısını bulma) için bir kullanıcı arabirimi ve sayfa modeli yöntemleri sağlar.
- İleti, iki özelliği olan
Messagesınıfı (Data/Message.cs) tarafından açıklanmıştır:Id(anahtar) veText(ileti). özelliğiTextgereklidir ve 200 karakterle sınırlıdır. - İletiler, Entity Framework'nin bellek içinde veritabanı depolama†.
- Uygulama, veritabanı bağlam sınıfında (
AppDbContextData/AppDbContext.cs) bir DAL içerir. DAL yöntemleri, testlerdevirtualkullanmak üzere sahte yöntemlere izin veren olarak işaretlenir. - Veritabanı uygulama başlangıcında boşsa, ileti deposu üç iletiyle başlatılır. Bu çekirdek iletileri testlerde de kullanılır.
†InMemory ile Testef konusu, MSTest ile testler için bellek içinde veritabanı kullanmayı açıklar. Bu konu, xUnit test çerçevesini kullanır. Farklı test çerçeveleri genelinde test kavramları ve test uygulamaları birbirine benzer ancak aynı değildir.
Örnek uygulama depo desenini kullanmasa da ve İş Birimi (UoW)deseninin etkili bir örneği değilse de, Sayfalar bu geliştirme Razor desenlerini destekler. Daha fazla bilgi için bkz. Altyapı kalıcılık katmanını tasarlama ASP.NET Core 'de test denetleyicisi mantığı ve (örnek depo desenini uygulama).
Test uygulaması kuruluşu
Test uygulaması, tests/ Razor PagesTestSample.Tests klasörünün içindeki bir konsol uygulamasıdır.
| Uygulama klasörünü test edin | Description |
|---|---|
| UnitTests |
|
| Yardımcı Programlar | Veritabanının her test için temel koşuluna sıfırlanacak şekilde her DAL birim testi için yeni veritabanı TestDbContextOptions bağlam seçenekleri oluşturmak için kullanılan yöntemini içerir. |
Test çerçevesi xUnit'tir. Nesne sahte çerçevesi Moq'larıdır.
Veri erişim katmanının (DAL) birim testleri
İleti uygulaması, sınıfında AppDbContext (src/ Razor PagesTestSample/Data/AppDbContext.cs) bulunan dört yöntemi içeren bir DAL içerir. Her yöntemin test uygulamasında bir veya iki birim testi vardır.
| DAL yöntemi | İşlev |
|---|---|
GetMessagesAsync |
özelliğine List<Message> göre sıralanmış veritabanından bir Text alır. |
AddMessageAsync |
Veritabanına Message bir ekler. |
DeleteAllMessagesAsync |
Veritabanındaki Message tüm girişleri siler. |
DeleteMessageAsync |
tarafından veritabanından Message tek bir Id siler. |
DAL'ın birim testleri, DbContextOptions her test için yeni bir oluşturma AppDbContext gerektirir. Her test için oluşturma DbContextOptions yaklaşımlarından biri kullanmak DbContextOptionsBuilder olacaktır:
var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("InMemoryDb");
using (var db = new AppDbContext(optionsBuilder.Options))
{
// Use the db here in the unit test.
}
Bu yaklaşımda sorun, her testin veritabanını önceki testin bıraktığı durumdan farklı bir şekilde aldığıdır. Bu, birbirini engellemeyen atomik birim testleri yazmaya çalışırken sorun yaratabilir. her AppDbContext test için yeni bir veritabanı bağlamı kullanmaya zorlamak için, yeni bir hizmet DbContextOptions sağlayıcısını temel alan bir örnek sağlar. Test uygulaması, sınıf yöntemini Utilities TestDbContextOptions (tests/ Razor PagesTestSample.Tests/Utilities/Utilities.cs) kullanarak bunu nasıl yapacaklarını gösterir:
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;
}
DAL birim DbContextOptions testlerinde kullanmak, her testin yeni bir veritabanı örneğiyle atomik olarak çalışmasına olanak sağlar:
using (var db = new AppDbContext(Utilities.TestDbContextOptions()))
{
// Use the db here in the unit test.
}
sınıfındaki DataAccessLayerTest (UnitTests/DataAccessLayerTest.cs) her test yöntemi benzer bir Arrange-Act-Assert desenini izler:
- Düzenleme: Veritabanı test için yapılandırılır ve/veya beklenen sonuç tanımlanır.
- Eylem: Test yürütülür.
- Onay: Test sonucu başarılı olup olmadığını belirlemek için onaylar yapılır.
Örneğin, DeleteMessageAsync yöntemi Id (src/ Razor Pagestestsample/Data/appdbcontext. cs) tarafından tanımlanan tek bir iletinin kaldırılmasından sorumludur:
public async virtual Task DeleteMessageAsync(int id)
{
var message = await Messages.FindAsync(id);
if (message != null)
{
Messages.Remove(message);
await SaveChangesAsync();
}
}
Bu yöntem için iki test vardır. Bir test, bir ileti veritabanında olduğunda yöntemin bir iletiyi sildiğini denetler. Diğer yöntem, silme iletisi yoksa veritabanının değişmediğini sınar Id . DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFoundYöntemi aşağıda gösterilmiştir:
[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));
}
}
İlk olarak, yöntemi, hareket adımının hazırlanması gereken düzenleme adımını gerçekleştirir. Dengeli dağıtım iletileri ' de alınır ve tutulur seedMessages . Dengeli dağıtım iletileri veritabanına kaydedilir. İçeren ileti Id 1 silinmek üzere ayarlanmış. DeleteMessageAsyncYöntemi yürütüldüğünde, beklenen iletilerde, ' ın dışında bir ileti olmalıdır Id 1 . expectedMessagesDeğişken, beklenen bu sonucu temsil eder.
// Arrange
var seedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(seedMessages);
await db.SaveChangesAsync();
var recId = 1;
var expectedMessages =
seedMessages.Where(message => message.Id != recId).ToList();
Yöntemi şu şekilde davranır: DeleteMessageAsync yöntemi ' ın içinde geçirme yürütülür recId 1 :
// Act
await db.DeleteMessageAsync(recId);
Son olarak, yöntemi bağlamını edinir Messages ve expectedMessages iki eşit olan asserile karşılaştırır:
// 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));
İki ikisinin de aynı olduğunu karşılaştırmak için List<Message> :
- İletiler tarafından sıralanır
Id. - İleti çiftleri özelliği ile karşılaştırılır
Text.
Benzer bir test yöntemi, DeleteMessageAsync_NoMessageIsDeleted_WhenMessageIsNotFound mevcut olmayan bir iletiyi silmeye çalışılması sonucunu denetler. Bu durumda, veritabanındaki beklenen iletiler, yöntem yürütüldükten sonra gerçek iletilere eşit olmalıdır DeleteMessageAsync . Veritabanının içeriğinde değişiklik olmamalıdır:
[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));
}
}
Sayfa modeli yöntemlerinin birim testleri
Başka bir birim testi kümesi, sayfa modeli yöntemlerinin sınamalarından sorumludur. İleti uygulamasında Dizin sayfası modelleri IndexModel src/ Razor pagestestsample/Pages/Index. cshtml. cs içindeki sınıfta bulunur.
| Sayfa modeli yöntemi | İşlev |
|---|---|
OnGetAsync |
Yöntemini kullanarak, Kullanıcı arabirimi için DAL öğesinden gelen iletileri alır GetMessagesAsync . |
OnPostAddMessageAsync |
ModelState geçerliyse, AddMessageAsync veritabanına bir ileti eklemek için çağırır. |
OnPostDeleteAllMessagesAsync |
DeleteAllMessagesAsyncVeritabanındaki tüm iletileri silmek için çağırır. |
OnPostDeleteMessageAsync |
DeleteMessageAsyncBelirtilen bir iletiyi silmek için yürütülür Id . |
OnPostAnalyzeMessagesAsync |
Veritabanında bir veya daha fazla ileti varsa, ileti başına ortalama sözcük sayısını hesaplar. |
Sayfa modeli yöntemleri, sınıfında yedi test kullanılarak test edilir IndexPageTests (testler/ Razor Pagestestsample. testler/unittests/ındexpagetests. cs). Testler tanıdık düzenleme-onaylama-Işlem düzeni kullanır. Bu sınamalar üzerinde odaklanılmıştır:
- ModelState geçersiz olduğunda yöntemlerin doğru davranışı izleyip izlemediğini belirleme.
- Yöntemlerin doğru bir şekilde ürettiği doğrulanıyor IActionResult .
- Özellik değeri atamalarının doğru şekilde yapıldığından emin olup olmadığı denetleniyor.
Bu test grubu genellikle, bir sayfa modeli yönteminin yürütüldüğü Işlem adımı için beklenen verileri oluşturmak üzere DAL yöntemlerini oluşturuyor. Örneğin, GetMessagesAsync öğesinin yöntemi AppDbContext Çıkış oluşturmak için kullanılır. Bir sayfa modeli yöntemi bu yöntemi yürüttüğünde, sahte sonuç döndürür. Veriler veritabanından gelmiyor. Bu, sayfa modeli testlerinde DAL kullanımı için öngörülebilir, güvenilir bir test koşulları oluşturur.
OnGetAsync_PopulatesThePageModel_WithAListOfMessagesTest, GetMessagesAsync yöntemin sayfa modeli için nasıl kullanılacağını gösterir:
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);
Yöntem, OnGetAsync işlem adımında yürütüldüğünde, sayfa modelinin GetMessagesAsync yöntemini çağırır.
Birim testi Işlem adımı (testler/ Razor pagestestsample. testler/unittests/ındexpagetests. cs):
// Act
await pageModel.OnGetAsync();
IndexPage sayfa modelinin OnGetAsync Yöntemi (src/ Razor pagestestsample/Pages/Index. cshtml. cs):
public async Task OnGetAsync()
{
Messages = await _db.GetMessagesAsync();
}
GetMessagesAsyncDal içindeki yöntemi bu yöntem çağrısının sonucunu döndürmez. Metodun moclenmiş sürümü sonucu döndürür.
AssertAdımda, gerçek iletiler ( actualMessages ) Messages sayfa modelinin özelliğinden atanır. İletiler atandığında bir tür denetimi de gerçekleştirilir. Beklenen ve gerçek iletiler Text özellikleriyle karşılaştırılır. Test, iki List<Message> örneğinin aynı iletileri içerdiğini onaylar.
// 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));
Bu gruptaki diğer testler,,, ve ' ı DefaultHttpContext ModelStateDictionary ActionContext kurmak için, PageContext ViewDataDictionary , bir içeren sayfa modeli nesneleri oluşturur PageContext . Bunlar, testleri yürütmek için faydalıdır. Örneğin, ileti uygulaması ModelState AddModelError yürütüldüğünde geçerli bir PageResult döndürülüp döndürüldüğünden emin olmak için bir hata oluşturur 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);
}
Ek kaynaklar
- DotNet test ve xUnit kullanarak .NET Core 'Da birim testi C#
- ASP.NET Core 'de test denetleyicisi mantığı
- kodunuzun birim testi (Visual Studio)
- ASP.NET Core tümleştirme testleri
- xUnit.net
- Mac için Visual Studio kullanarak macOS’ta eksiksiz bir .NET Core çözümü derleme
- XUnit.net kullanmaya başlama: .NET SDK komut satırı ile .NET Core kullanma
- Moq dili
- Moq hızlı başlangıç
- JustMockLite: .NET geliştiricileri için bir sahte işlem çerçevesi. (Microsoft tarafından korunmaz veya desteklenmez.)