Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Teď, když jsou vaše ViewModely a služby ve samostatné knihovně tříd, můžete snadno vytvářet jednotkové testy. Přidání projektů testů jednotek umožňuje ověřit, že se modely ViewModel a služby chovají podle očekávání, aniž by se museli spoléhat na vrstvu uživatelského rozhraní nebo ruční testování. Testy jednotek můžete spouštět automaticky jako součást vývojového pracovního postupu a zajistit tak, aby váš kód zůstal spolehlivý a udržovatelný.
Vytvoření projektu testování jednotek
- V Průzkumníku řešení klikněte pravým tlačítkem myši na řešení.
- Vyberte Přidat>nový projekt....
- Zvolte šablonu aplikace Pro testování jednotek WinUI a vyberte Další.
- Pojmenujte projekt
WinUINotes.Testsa vyberte Vytvořit.
Přidání odkazů na projekt
- Klikněte pravým tlačítkem myši na projekt WinUINotes.Tests a vyberte Přidat>odkaz na projekt....
- Zkontrolujte projekt WinUINotes.Bus a vyberte OK.
Vytváření falešných implementací pro testování
Pro účely testování vytvořte falešné implementace souborové služby a tříd úložiště, které ve skutečnosti nezapisují na disk. Fakes jsou jednoduché implementace, které simulují chování skutečných závislostí pro účely testování.
V projektu WinUINotes.Tests vytvořte novou složku s názvem Fakes.
Přidejte soubor
FakeFileService.cstřídy do složky 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; } } }Používá
FakeFileServiceslovník v paměti (fileStorage) k simulaci operací se soubory bez zásahu do skutečného systému souborů. Mezi klíčové funkce patří:-
Asynchronní simulace: Používá
Task.Delay(10)se k napodobení skutečných asynchronních operací se soubory. - Ověřování: Vyvolá výjimky pro neplatné vstupy, stejně jako skutečná implementace.
-
Integrace s falešnými třídami úložiště: Vrácení
FakeStorageFolderaFakeStorageFileinstance, které spolupracují na simulaci rozhraní API služby Windows Storage
-
Asynchronní simulace: Používá
Přidat
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 ... } }Konstruktor
FakeStorageFolderpřijímá slovník úložiště souborů, což mu umožňuje pracovat se stejným systémem souborů v paměti jakoFakeFileService. Většina členů rozhraní vyvolá výjimkuNotImplementedException, protože je potřeba implementovat pouze vlastnosti a metody, které testy skutečně používají.Pro účely tohoto kurzu si můžete prohlédnout úplnou implementaci
FakeStorageFolderv úložišti kódu GitHubu .Přidat
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 ... } }Objekt
FakeStorageFilepředstavuje jednotlivé soubory v systému falešného úložiště. Uloží název souboru a poskytuje minimální implementaci potřebnou pro testy. Podobně jakoFakeStorageFolderimplementuje pouze členy, které skutečně používá testovaný kód.Pro účely tohoto kurzu si můžete prohlédnout úplnou implementaci
FakeStorageFolderv úložišti kódu GitHubu .
Další informace najdete v dokumentaci:
Napište jednoduchý jednotkový test
Přejmenujte
UnitTest1.csnaNoteTests.csa aktualizujte ho: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); } } }Tento test ukazuje, jak pomocí
FakeFileServicetestovat jednotkuNoteViewModel. Test vytvoří novýNoteViewModel, zkontroluje jeho počáteční stav (datum je poslední, název souboru se řídí očekávaným vzorem), nastaví text na poznámce, spustí příkaz uložit a potvrdí, že text přetrvává. Vzhledem k tomu, že falešná souborová služba se používá místo skutečné implementace, test se spustí rychle bez skutečného vstupně-výstupního souboru a může běžet opakovaně bez vedlejších účinků.
Další informace najdete v dokumentaci:
Spuštění testů
- Otevřete okno Průzkumníka testů v sadě Visual Studio (Průzkumník testů>).
- Vyberte Spustit všechny testy a spusťte test jednotek.
- Ověřte, že test projde.
Teď máte testovatelnou architekturu, ve které můžete testovat modely ViewModel a služby nezávisle na uživatelském rozhraní.
Shrnutí
V této sérii kurzů jste se naučili:
- Vytvořte samostatný projekt knihovny tříd (Bus project), který bude obsahovat ViewModely a služby, což umožňuje jednotkové testování odděleně od vrstvy uživatelského rozhraní.
- Implementujte model MVVM pomocí MVVM Toolkit, využitím atributů
ObservableObject,[ObservableProperty]a[RelayCommand]pro redukci nadbytečného kódu. - Pomocí generátorů zdrojů můžete automaticky vytvářet oznámení o změnách vlastností a implementace příkazů.
- Slouží
[NotifyCanExecuteChangedFor]k automatické aktualizaci dostupnosti příkazů při změně hodnot vlastností. - Integrujte injektáž závislostí pomocí
Microsoft.Extensions.DependencyInjectionpro řízení životního cyklu modelů „ViewModels“ a služeb. -
IFileServiceVytvořte rozhraní a implementaci pro zpracování operací se soubory testovatelným způsobem. - Nakonfigurujte kontejner DI v
App.xaml.csa načtěte ViewModely od poskytovatele služeb na stránkách. -
WeakReferenceMessengerImplementujte povolení volné vazby mezi součástmi, což umožňuje stránkám reagovat na události ViewModel bez přímých odkazů. - Vytvořte třídy zpráv, které dědí z
ValueChangedMessage<T>, aby přenášely data mezi komponentami. - Vytvářejte falešné implementace závislostí pro testování, aniž byste se museli dotýkat skutečného systému souborů.
- Pište jednotkové testy pomocí MSTest pro ověření chování ViewModelu nezávisle na vrstvě uživatelského rozhraní.
Tato architektura poskytuje solidní základ pro vytváření udržovatelných, testovatelných aplikací WinUI s jasným oddělením obav mezi uživatelským rozhraním, obchodní logikou a vrstvami přístupu k datům. Kód pro účely tohoto kurzu si můžete stáhnout nebo zobrazit z úložiště GitHub.
Další kroky
Teď, když rozumíte tomu, jak implementovat MVVM pomocí MVVM Toolkit a injektáž závislostí, můžete prozkoumat pokročilejší témata:
- Pokročilé zasílání zpráv: Prozkoumejte další vzory zasílání zpráv, včetně zpráv žádostí a odpovědí a tokenů zpráv pro selektivní zpracování zpráv.
- Ověření: Přidejte do modelů ViewModel vstupní ověřování pomocí datových poznámek a ověřovacích funkcí MVVM Toolkit.
-
Asynchronní příkazy: Přečtěte si další informace o asynchronním spouštění příkazů, podpoře zrušení a vykazování průběhu pomocí
AsyncRelayCommand. - Rozšířené testování: Prozkoumejte pokročilejší scénáře testování, včetně testování zpracování zpráv, asynchronního spouštění příkazů a oznámení o změnách vlastností.
-
Pozorovatelné kolekce: Efektivně používejte
ObservableCollection<T>a prozkoumejteObservableRangeCollection<T>pro hromadné operace.
Související obsah
- Dokumentace k MVVM Toolkit
- Sada nástrojů .NET Community Toolkit
- Kurz vytvoření aplikace WinUI
- Přehled datových vazeb
- Injektáž závislostí v .NET
- jednotkové testování v .NET
- Ukázky MVVM Toolkit na GitHubu
Windows developer