Not
Åtkomst till denna sida kräver auktorisation. Du kan prova att logga in eller byta katalog.
Åtkomst till denna sida kräver auktorisation. Du kan prova att byta katalog.
Nu när dina ViewModels och tjänster finns i ett separat klassbibliotek kan du enkelt skapa enhetstester. Genom att lägga till enhetstestprojekt kan du kontrollera att dina ViewModels och tjänster fungerar som förväntat utan att förlita sig på användargränssnittsskiktet eller manuell testning. Du kan köra enhetstester automatiskt som en del av ditt arbetsflöde för utveckling, vilket säkerställer att koden förblir tillförlitlig och underhållsbar.
Skapa ett enhetstestprojekt
- Högerklicka på lösningen i Solution Explorer.
- Välj Lägg till>nytt projekt....
- Välj mallen WinUI Unit Test App och välj Nästa.
- Ge projektet namnet
WinUINotes.Testsoch välj Skapa.
Lägga till projektreferenser
- Högerklicka på projektet WinUINotes.Tests och välj Lägg till>projektreferens....
- Kontrollera WinUINotes.Bus-projektet och välj OK.
Skapa falska implementeringar för testning
För testning skapar du falska implementeringar av filtjänst- och lagringsklasserna som faktiskt inte skriver till disk. Förfalskningar är enkla implementeringar som simulerar beteendet hos verkliga beroenden i testsyfte.
I projektet WinUINotes.Tests skapar du en ny mapp med namnet Fakes.
Lägg till en klassfil
FakeFileService.csi mappen Fakes:using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Windows.Storage; using WinUINotes.Services; namespace WinUINotes.Tests.Fakes { internal class FakeFileService : IFileService { private Dictionary<string, string> fileStorage = []; public async Task CreateOrUpdateFileAsync(string filename, string contents) { if (fileStorage.ContainsKey(filename)) { fileStorage[filename] = contents; } else { fileStorage.Add(filename, contents); } await Task.Delay(10); // Simulate some async work } public async Task DeleteFileAsync(string filename) { if (fileStorage.ContainsKey(filename)) { fileStorage.Remove(filename); } await Task.Delay(10); // Simulate some async work } public bool FileExists(string filename) { if (string.IsNullOrEmpty(filename)) { throw new ArgumentException("Filename cannot be null or empty", nameof(filename)); } if (fileStorage.ContainsKey(filename)) { return true; } return false; } public IStorageFolder GetLocalFolder() { return new FakeStorageFolder(fileStorage); } public async Task<IReadOnlyList<IStorageItem>> GetStorageItemsAsync() { await Task.Delay(10); return GetStorageItemsInternal(); } public async Task<IReadOnlyList<IStorageItem>> GetStorageItemsAsync(IStorageFolder storageFolder) { await Task.Delay(10); return GetStorageItemsInternal(); } private IReadOnlyList<IStorageItem> GetStorageItemsInternal() { return fileStorage.Keys.Select(filename => CreateFakeStorageItem(filename)).ToList(); } private IStorageItem CreateFakeStorageItem(string filename) { return new FakeStorageFile(filename); } public async Task<string> GetTextFromFileAsync(IStorageFile file) { await Task.Delay(10); if (fileStorage.ContainsKey(file.Name)) { return fileStorage[file.Name]; } return string.Empty; } } }FakeFileServiceAnvänder en minnesintern ordlista (fileStorage) för att simulera filåtgärder utan att röra det faktiska filsystemet. Viktiga funktioner är:-
Async-simulering: Används
Task.Delay(10)för att efterlikna verkliga asynkrona filåtgärder - Validering: Utlöser undantag för ogiltiga indata, precis som den verkliga implementeringen
-
Integrering med falska lagringsklasser: Returnerar
FakeStorageFolderochFakeStorageFileinstanser som fungerar tillsammans för att simulera Windows Storage-API:et
-
Async-simulering: Används
Lägg till
FakeStorageFolder.cs:using System; using System.Collections.Generic; using System.Runtime.InteropServices.WindowsRuntime; using Windows.Foundation; using Windows.Storage; using Windows.Storage.FileProperties; using Windows.Storage.Search; namespace WinUINotes.Tests.Fakes { internal class FakeStorageFolder : IStorageFolder { private string name; private Dictionary<string, string> fileStorage = []; public FakeStorageFolder(Dictionary<string, string> files) { fileStorage = files; } public FileAttributes Attributes => throw new NotImplementedException(); public DateTimeOffset DateCreated => throw new NotImplementedException(); public string Name => name; public string Path => throw new NotImplementedException(); public IAsyncOperation<StorageFile> CreateFileAsync(string desiredName) { throw new NotImplementedException(); } public IAsyncOperation<StorageFile> CreateFileAsync(string desiredName, CreationCollisionOption options) { throw new NotImplementedException(); } public IAsyncOperation<StorageFolder> CreateFolderAsync(string desiredName) { throw new NotImplementedException(); } // Only partial implementation shown for brevity ... } }FakeStorageFoldertar fillagringsordlistan i konstruktorn så att den kan fungera med samma minnesinterna filsystem somFakeFileService. De flesta gränssnittsmedlemmar genererarNotImplementedExceptioneftersom endast de egenskaper och metoder som faktiskt används av testerna måste implementeras.Du kan visa den fullständiga implementeringen av
FakeStorageFolderi GitHub-kodförrådet för denna handledning.Lägg till
FakeStorageFile.cs:using System; using System.IO; using System.Runtime.InteropServices.WindowsRuntime; using Windows.Foundation; using Windows.Storage; using Windows.Storage.FileProperties; using Windows.Storage.Streams; namespace WinUINotes.Tests.Fakes { public class FakeStorageFile : IStorageFile { private string name; public FakeStorageFile(string name) { this.name = name; } public string ContentType => throw new NotImplementedException(); public string FileType => throw new NotImplementedException(); public FileAttributes Attributes => throw new NotImplementedException(); public DateTimeOffset DateCreated => throw new NotImplementedException(); public string Name => name; public string Path => throw new NotImplementedException(); public IAsyncOperation<StorageFile> CopyAsync(IStorageFolder destinationFolder) { throw new NotImplementedException(); } public IAsyncOperation<StorageFile> CopyAsync(IStorageFolder destinationFolder, string desiredNewName) { throw new NotImplementedException(); } public IAsyncOperation<StorageFile> CopyAsync(IStorageFolder destinationFolder, string desiredNewName, NameCollisionOption option) { throw new NotImplementedException(); } public IAsyncAction CopyAndReplaceAsync(IStorageFile fileToReplace) { throw new NotImplementedException(); } // Only partial implementation shown for brevity ... } }Representerar
FakeStorageFileenskilda filer i det falska lagringssystemet. Den lagrar filnamnet och ger den minimala implementering som krävs för testerna. Precis somFakeStorageFolderimplementerar den bara de medlemmar som faktiskt används av koden som testas.Du kan visa den fullständiga implementeringen av
FakeStorageFolderi GitHub-kodlagringsplatsen för denna handledning.
Läs mer i dokumenten:
Skriva ett enkelt enhetstest
Byt
UnitTest1.csnamn påNoteTests.csoch uppdatera det:using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using WinUINotes.Tests.Fakes; namespace WinUINotes.Tests { [TestClass] public partial class NoteTests { [TestMethod] public void TestCreateUnsavedNote() { var noteVm = new ViewModels.NoteViewModel(new FakeFileService()); Assert.IsNotNull(noteVm); Assert.IsTrue(noteVm.Date > DateTime.Now.AddHours(-1)); Assert.IsTrue(noteVm.Filename.EndsWith(".txt")); Assert.IsTrue(noteVm.Filename.StartsWith("notes")); noteVm.Text = "Sample Note"; Assert.AreEqual("Sample Note", noteVm.Text); noteVm.SaveCommand.Execute(null); Assert.AreEqual("Sample Note", noteVm.Text); } } }Det här testet visar hur du enhetstestar
NoteViewModelmed hjälpFakeFileServiceav . Testet skapar ett nyttNoteViewModel, kontrollerar dess ursprungliga tillstånd (datumet är nyligen, filnamnet följer det förväntade mönstret), anger text på anteckningen, kör kommandot spara och bekräftar att texten bevaras. Eftersom den falska filtjänsten används i stället för den verkliga implementeringen körs testet snabbt utan någon faktisk fil-I/O och kan köras upprepade gånger utan biverkningar.
Läs mer i dokumenten:
Kör testerna
- Öppna testutforskarens fönster i Visual Studio (Test>Test Explorer).
- Välj Kör alla tester för att köra enhetstestet.
- Kontrollera att testet har godkänts.
Nu har du en testbar arkitektur där du kan testa dina ViewModels och tjänster oberoende av användargränssnittet!
Sammanfattning
I den här självstudieserien lärde du dig att:
- Skapa ett separat klassbiblioteksprojekt (Bus-projekt) för att lagra dina ViewModels och tjänster, vilket möjliggör enhetstestning separat från användargränssnittsskiktet.
- Implementera MVVM-mönstret med hjälp av MVVM Toolkit, utnyttja
ObservableObject,[ObservableProperty]attribut och[RelayCommand]för att minska standardkoden. - Använd källgeneratorer för att automatiskt skapa meddelanden om egenskapsändring och kommandoimplementeringar.
- Använd
[NotifyCanExecuteChangedFor]för att automatiskt uppdatera kommandotillgängligheten när egenskapsvärdena ändras. - Integrera beroendeinmatning med hjälp av
Microsoft.Extensions.DependencyInjectionför att hantera livscykeln för ViewModels och tjänster. - Skapa ett
IFileServicegränssnitt och en implementering för att hantera filåtgärder på ett testbart sätt. - Konfigurera DI-containern i
App.xaml.csoch hämta ViewModels från tjänstleverantören på dina sidor. -
WeakReferenceMessengerImplementera för att aktivera lös koppling mellan komponenter så att sidorna kan svara på ViewModel-händelser utan direkta referenser. - Skapa meddelandeklasser som ärver från
ValueChangedMessage<T>för att överföra data mellan komponenter. - Skapa falska implementeringar av beroenden för testning utan att röra det faktiska filsystemet.
- Skriv enhetstester med MSTest för att verifiera ViewModel-beteendet oberoende av användargränssnittsskiktet.
Den här arkitekturen ger en solid grund för att skapa underhållsbara, testbara WinUI-program med tydlig uppdelning av problem mellan användargränssnittet, affärslogik och dataåtkomstskikt. Du kan ladda ned eller visa koden för den här självstudien från GitHub-lagringsplatsen.
Nästa steg
Nu när du förstår hur du implementerar MVVM med MVVM Toolkit och beroendeinmatning kan du utforska mer avancerade ämnen:
- Avancerade meddelanden: Utforska ytterligare meddelandemönster, inklusive begärande-/svarsmeddelanden och meddelandetoken för selektiv meddelandehantering.
- Validering: Lägg till indataverifiering i dina ViewModels med hjälp av dataanteckningar och valideringsfunktionerna för MVVM Toolkit.
-
Async-kommandon: Läs mer om asynkron kommandokörning, support för annullering och förloppsrapportering med
AsyncRelayCommand. - Avancerad testning: Utforska mer avancerade testscenarier, inklusive testning av meddelandehantering, asynkron kommandokörning och meddelanden om egenskapsändring.
-
Observerbara samlingar: Använd
ObservableCollection<T>effektivt och utforskaObservableRangeCollection<T>för storskaliga operationer.
Relaterat innehåll
Windows developer