This repository was archived by the owner on May 1, 2024. It is now read-only.
This repository was archived by the owner on May 1, 2024. It is now read-only.
[Bug] AsyncCommand is not testable #825
Closed
Description
Description
Priviously we used DelegateCommand
from Prism library but want to switch to AsyncCommands now. One of the reasons was, to be able to test easier commands with async actions behind them (most of them).
If we try to unit test our view models with AsyncCommand
, the executeion fails due to hard dependecy on Device.BeginInvokeOnMainThread
method.
Steps to Reproduce
- Create a view model with an
AsyncCommand
- Create unit test, to test the execution of this command
- Test fails with exception
Expected Behavior
It should be possible to test view models, without initializing Xamarin.Forms
Actual Behavior
Basic Information
- Version with issue: 1.0.2
- Last known good version: unknown
- IDE: VS 2019 16.8.4
- Platform Target Frameworks: NUinit with on .Net Core 3.1 project
Workaround
Not using AsyncCommand!
Reproduction imagery
[Test]
public async Task ResultCommand_Returns()
{
// Arrange
var expected = "returned result";
var nav = Mock.Of<ICommonNavigationService>();
var result = new Result(expected, new byte[0], new ResultPoint[0], BarcodeFormat.QR_CODE);
var sut = CreateViewModel(nav);
// Act
await sut.ResultCommand.ExecuteAsync(result);
// Assert
Mock.Get(nav).Verify(v => v.ToPreviousWithDataAsync(CommonConstants.NavigationKeys.QR_CODE_CONTENT, expected), Times.Once);
}
Example
Log output
System.InvalidOperationException : You must call Xamarin.Forms.Forms.Init(); prior to using this property.
at Xamarin.Forms.Device.get_PlatformServices()
at Xamarin.Forms.Device.BeginInvokeOnMainThread(Action action)
at Xamarin.CommunityToolkit.ObjectModel.Internals.BaseCommand`1.RaiseCanExecuteChanged()
at Xamarin.CommunityToolkit.ObjectModel.Internals.BaseCommand`1.set_ExecutionCount(Int32 value)
at Xamarin.CommunityToolkit.ObjectModel.Internals.BaseAsyncCommand`2.ExecuteAsync(TExecute parameter)
at Xamarin.Common.Tests.ViewModels.QrScanViewModelTests.ResultCommand_Returns() in C:\src\XF Libs\Xamarin.Common-69-xamarin_forms_5\tests\Xamarin.Common.Tests\ViewModels\QrScanViewModelTests.cs:line 60
at NUnit.Framework.Internal.TaskAwaitAdapter.GenericAdapter`1.GetResult()
at NUnit.Framework.Internal.AsyncToSyncAdapter.Await(Func`1 invoke)
at NUnit.Framework.Internal.Commands.TestMethodCommand.RunTestMethod(TestExecutionContext context)
at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context)
at NUnit.Framework.Internal.Execution.SimpleWorkItem.<>c__DisplayClass4_0.<PerformWork>b__0()
at NUnit.Framework.Internal.ContextUtils.<>c__DisplayClass1_0`1.<DoIsolated>b__0(Object _)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at NUnit.Framework.Internal.ContextUtils.DoIsolated(ContextCallback callback, Object state)
at NUnit.Framework.Internal.ContextUtils.DoIsolated[T](Func`1 func)
at NUnit.Framework.Internal.Execution.SimpleWorkItem.PerformWork()
I suppose, the following line produce the problem: