当ContinueWith与System.Threading.Tasks.Task一起使用时,单元测试失败

Md.*_*far 6 c# nunit unit-testing moq task-parallel-library

我正在尝试为我的代码添加单元测试,我在TaskTPL中使用它来将值更新到数据库中.对于单元测试,我正在使用NUnitMoq.以下是我项目中的一些代码片段.

*//service*
public interface IServiceFacade{
   Task SynchronizeDataset (string datasetName);
}

*//The method call I want to test*
_ServiceFacade.SynchronizeDataset(DATASET_NAME);

*//In my test, I want to verify if this method is called*
mock_IServicesFacade.Setup(sf => sf.SynchronizeDataset(It.IsAny<string>())).Returns(It.IsAny<Task>());
presenter.InitializeView();
mock_IServicesFacade.Verify(sf => sf.SynchronizeDataset(NSUserUtilStrings.DATASET_ACHIEVEMENT), Times.Once());
Run Code Online (Sandbox Code Playgroud)

这很有效.但是当我添加这样ContinueWith的服务方法调用时...

_ServiceFacade.SynchronizeDataset(DATASET_NAME).ContinueWith(t =>
{
    if (t.IsFaulted)
    {
        //do something
    }
});
Run Code Online (Sandbox Code Playgroud)

此测试代码无法正常工作.测试失败并显示此错误...

System.NullReferenceException:未将对象引用设置为对象的实例

堆栈跟踪:

DevicePategoryPresenterTest.cs中的atPresenters.UnitTests.DeviceCategoryPresenterTest.InitializeView_Called()[0x00241]:56(托管管理到本机)System.Reflection.MonoMethod:InternalInvoke(System.Reflection.MonoMethod,object,object [],System.Exception& )在System.Reflection.MonoMethod.Invoke(System.Object obj,System.Reflection.BindingFlags invokeAttr,System.Reflection.Binder binder,System.Object [] parameters,System.Globalization.CultureInfo culture)[0x00038] in/private/TMP /源 - 单 - 4.8.0/bockbuild - 单4.8.0分支/简档/单MAC-xamarin /建立根/单声道86/MCS /类/ corlib /的System.Reflection/MonoMethod.cs: 305

我不知道如何解决它.请帮忙.提前致谢.

Joh*_*nny 4

事实上,您通过传递有效任务而不是 来跳过延续It.IsAny<Task>。一个例子是做这样的事情

.NET < v4.6

mock_IServicesFacade
    .Setup(sf => sf.SynchronizeDataset(It.IsAny<string>()))
    .Returns(Task.FromResult(true)))
Run Code Online (Sandbox Code Playgroud)

.NET >= v4.6

mock_IServicesFacade
    .Setup(sf => sf.SynchronizeDataset(It.IsAny<string>()))
    .Returns(Task.CompletedTask))
Run Code Online (Sandbox Code Playgroud)

您甚至可以尝试使用选项进行延续,TaskContinuationOptions.OnlyOnFaulted因为您只对场景感兴趣IsFaulted

请注意,您不是在测试延续部分,只是跳过它。如果您确实想测试\验证延续部分,请小心。看来您的逻辑是服务端逻辑,因此TaskScheduler将在线程上使用默认值SynchronizationContext和计划延续ThreadPool。当然,这是在相同的单元测试运行器上下文中执行的。基本上,您的测试甚至可以在执行继续任务之前完成。