You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Dec 15, 2024. It is now read-only.
{
"@context": "http://schema.org",
"@type": "BlogPosting",
"author": {
"@type": "Person",
"name": "Laurent Kempé",
"sameAs": [
"https://github.com/laurentkempe",
"https://twitter.com/laurentkempe",
"https://www.linkedin.com/in/laurentkempe",
"https://flickr.com/photos/laurentkempe/"
],
"image": "https://farm2.staticflickr.com/1971/31306281378_02b055ccfe_q.jpg"
},
"articleBody": "In the past, within my team at Innoveo, we had several discussions about the best way to unit test async WPF ICommand. We value quality, so testing is essential to us. We decided to make the methods called by the command internal so that our tests could call those.\nWhat is the problem with unit testing an Async WPF ICommand? The problem is that the command is an async void method! So, you have no way to await the end of the execution of your command. So, your test might assert on things that are still executing.\n\nSome weeks ago, a question about “Extract and Override call” taken from the book “Working Effectively with Legacy Code” for testing was raised on the French DevApps community. I immediately thought of the discussions about testing async WPF ICommand and proposed that solution as a pragmatic solution that is not only easy to implement but also very simple to understand. Some did not like that solution because it was not perfect. I agree, but sometimes it is good to be pragmatic.\nThe discussion went further about async void testing and Gérald Barré from Meziantou’s blog, which I highly recommend, answered it interestingly! He made a blog post about his solution “Awaiting an async void method in .NET“ which leverage his own implementation of a SynchronizationContext and TaskCompletionSource.\nI decided to apply his solution to our original question; “How to test an async WPF ICommand”?\nI quickly created a small .NET 6 WPF project and added to it the Windows Community Toolkit MVVM nuget. I copy-pasted the code from Gérald to it and wrote the following tests.\nMainWindowViewModelTests.cs123456789101112131415161718192021222324[TestFixture]public class MainWindowViewModelTests{ [Test] public void Click_FailingToAwaitCommandExecution() { var mainWindowViewModel = new MainWindowViewModel(); mainWindowViewModel.Click.Execute(null); Assert.That(mainWindowViewModel.Upper, Is.EqualTo("BEFORE")); } [Test] public async Task Click_ExpectUpperToBeUpperCase() { var mainWindowViewModel = new MainWindowViewModel(); await AsyncVoidSynchronizationContext.Run( () => mainWindowViewModel.Click.Execute(null)); Assert.That(mainWindowViewModel.Upper, Is.EqualTo("BEFORE")); }}\n\nThe first one fails because nothing awaits the execution of the WPF command. The second one succeeds because the test is awaiting the command execution. Nice, very nice!\nAnd here is the code of the MainWindowViewModel class.\nMainWindowViewModel.cs1234567891011121314151617181920public class MainWindowViewModel : ObservableObject{ private ICommand? _click; private string _upper = "before"; public ICommand Click => _click ??= new AsyncRelayCommand(Execute); public string Upper { get => _upper; set => SetProperty(ref _upper, value); } private async Task Execute() { await Task.Delay(2000); Upper = Upper.ToUpper(); }}\n\nSo, that is one way of solving testing an async WPF ICommand. But it is not the only way.\nWindows Community Toolkit MVVM provides the AsyncRelayCommand which implements IAsyncRelayCommand providing an ExecuteAsync method returning a Task which can be awaited.\n123456789[Test]public async Task OtherClick_ExpectUpperToBeUpperCase(){ var mainWindowViewModel = new MainWindowViewModel(); await mainWindowViewModel.OtherClick.ExecuteAsync(null); Assert.That(mainWindowViewModel.Upper, Is.EqualTo("BEFORE"));}\n\nAnd in this case we need to declare the command as an IAsyncRelayCommand\n123private IAsyncRelayCommand? _otherClick;public IAsyncRelayCommand OtherClick => _otherClick ??= new AsyncRelayCommand(Execute);\n\nand use the ExecuteAsync method in our test\n123456789[Test]public async Task OtherClick_ExpectUpperToBeUpperCase(){ var mainWindowViewModel = new MainWindowViewModel(); await mainWindowViewModel.OtherClick.ExecuteAsync(null); Assert.That(mainWindowViewModel.Upper, Is.EqualTo("BEFORE"));}\n\nConclusionAs a developer, I think it is always good to be pragmatic but this does not avoid to search for better solutions.\n\n\n \n\n\n\n",
"dateCreated": "2022-02-10T19:37:38+00:00",
"dateModified": "2022-02-10T19:42:55+00:00",
"datePublished": "2022-02-10T19:37:38+00:00",
"description": "In the past, within my team at Innoveo, we had several discussions about the best way to unit test async WPF ICommand. We value quality, so testing is essential to us. We decided to make the methods called by the command internal so that our tests could call those.\nWhat is the problem with unit testing an Async WPF ICommand? The problem is that the command is an async void method! So, you have no way to await the end of the execution of your command. So, your test might assert on things that are still executing.",
"headline": "Unit testing Async WPF ICommand",
"image": [
"https://live.staticflickr.com/65535/51872954907_ef93021c01_q.jpg",
"https://live.staticflickr.com/65535/51872954907_2104a32913_h.jpg"
],
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://laurentkempe.com/2022/02/10/unit-testing-async-wpf-icommand/"
},
"publisher": {
"@type": "Organization",
"name": "Laurent Kempé",
"sameAs": [
"https://github.com/laurentkempe",
"https://twitter.com/laurentkempe",
"https://www.linkedin.com/in/laurentkempe",
"https://flickr.com/photos/laurentkempe/"
],
"image": "https://farm2.staticflickr.com/1971/31306281378_02b055ccfe_q.jpg",
"logo": {
"@type": "ImageObject",
"url": "https://farm2.staticflickr.com/1971/31306281378_02b055ccfe_q.jpg"
}
},
"url": "https://laurentkempe.com/2022/02/10/unit-testing-async-wpf-icommand/",
"keywords": "WPF, .NET, unit test, C#",
"thumbnailUrl": "https://live.staticflickr.com/65535/51872954907_ef93021c01_q.jpg"
}
The text was updated successfully, but these errors were encountered:
See doc json-ld.org
Some .NET libraries exists like
See if something already exists for Statiq or implement a new component
Example for https://laurentkempe.com/2022/02/10/unit-testing-async-wpf-icommand/
The text was updated successfully, but these errors were encountered: