MVVM 在单元测试 MxvAsyncCommand 时交叉空引用
MVVM Cross null references when unit testing MxvAsyncCommand
我们最近升级到 MvvMCross 6.2.2 并注意到我们必须更改为使用 Mvx.IoCProvider。
我们发现,如果我们在 ViewModel 中构造 MvxAsyncCommand,这会导致调用此构造函数的所有单元测试出现空引用异常
*
Result StackTrace:
at MvvmCross.Commands.MvxCommandBase..ctor()
at MvvmCross.Commands.MvxAsyncCommand..ctor(Func`1 execute, Func`1 canExecute, Boolean allowConcurrentExecutions)
at App.Mobile.Core.ViewModels.TestViewModel..ctor(IMvxNavigationService navigation, ITestService encService, ILogger logger)
at App.Mobile.Core.UnitTests.TestViewModelTests.<TestViewModel_Prepare>d__1.MoveNext()
*
查看 github 中的源代码,问题是由于 Mvx.IocProvider 为空。
public MvxCommandBase()
{
if (!Mvx.IoCProvider.TryResolve<IMvxCommandHelper>(out _commandHelper))
_commandHelper = new MvxWeakCommandHelper();
var alwaysOnUIThread = MvxSingletonCache.Instance == null || MvxSingletonCache.Instance.Settings.AlwaysRaiseInpcOnUserInterfaceThread;
ShouldAlwaysRaiseCECOnUserInterfaceThread = alwaysOnUIThread;
}
已在 "develop" 分支中实施修复,但这在 nuget 上不可用。
public MvxCommandBase()
{
// fallback on MvxWeakCommandHelper if no IoC has been set up
if (!Mvx.IoCProvider?.TryResolve(out _commandHelper) ?? true)
_commandHelper = new MvxWeakCommandHelper();
// default to true if no Singleton Cache has been set up
var alwaysOnUIThread = MvxSingletonCache.Instance?.Settings.AlwaysRaiseInpcOnUserInterfaceThread ?? true;
ShouldAlwaysRaiseCECOnUserInterfaceThread = alwaysOnUIThread;
}
有谁知道在我们的单元测试项目中初始化此 IoCProvider 的解决方法。
如您所见here IoCProvider
是通过获取 IMvxIoCProvider
的单例来解决的
public static IMvxIoCProvider IoCProvider => MvxSingleton<IMvxIoCProvider>.Instance;
所以你所要做的就是初始化IMvxIoCProvider
。
作为一个例子,你可以使用 this test,所以为了初始化它,你必须这样做:
MvxSingleton.ClearAllSingletons(); // This should be done in the test to clear all references of previous tests if necessary.
var instance = MvxIoCProvider.Initialize();
高
我们最近升级到 MvvMCross 6.2.2 并注意到我们必须更改为使用 Mvx.IoCProvider。
我们发现,如果我们在 ViewModel 中构造 MvxAsyncCommand,这会导致调用此构造函数的所有单元测试出现空引用异常
*
Result StackTrace:
at MvvmCross.Commands.MvxCommandBase..ctor()
at MvvmCross.Commands.MvxAsyncCommand..ctor(Func`1 execute, Func`1 canExecute, Boolean allowConcurrentExecutions)
at App.Mobile.Core.ViewModels.TestViewModel..ctor(IMvxNavigationService navigation, ITestService encService, ILogger logger)
at App.Mobile.Core.UnitTests.TestViewModelTests.<TestViewModel_Prepare>d__1.MoveNext()
*
查看 github 中的源代码,问题是由于 Mvx.IocProvider 为空。
public MvxCommandBase()
{
if (!Mvx.IoCProvider.TryResolve<IMvxCommandHelper>(out _commandHelper))
_commandHelper = new MvxWeakCommandHelper();
var alwaysOnUIThread = MvxSingletonCache.Instance == null || MvxSingletonCache.Instance.Settings.AlwaysRaiseInpcOnUserInterfaceThread;
ShouldAlwaysRaiseCECOnUserInterfaceThread = alwaysOnUIThread;
}
已在 "develop" 分支中实施修复,但这在 nuget 上不可用。
public MvxCommandBase()
{
// fallback on MvxWeakCommandHelper if no IoC has been set up
if (!Mvx.IoCProvider?.TryResolve(out _commandHelper) ?? true)
_commandHelper = new MvxWeakCommandHelper();
// default to true if no Singleton Cache has been set up
var alwaysOnUIThread = MvxSingletonCache.Instance?.Settings.AlwaysRaiseInpcOnUserInterfaceThread ?? true;
ShouldAlwaysRaiseCECOnUserInterfaceThread = alwaysOnUIThread;
}
有谁知道在我们的单元测试项目中初始化此 IoCProvider 的解决方法。
如您所见here IoCProvider
是通过获取 IMvxIoCProvider
public static IMvxIoCProvider IoCProvider => MvxSingleton<IMvxIoCProvider>.Instance;
所以你所要做的就是初始化IMvxIoCProvider
。
作为一个例子,你可以使用 this test,所以为了初始化它,你必须这样做:
MvxSingleton.ClearAllSingletons(); // This should be done in the test to clear all references of previous tests if necessary.
var instance = MvxIoCProvider.Initialize();
高