我面对的是,当单元测试使用任务延续和DispatcherSynchrinizationContext代码我不明白的问题。
我的单元测试代码:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext());
var class1 = new Class1();
var result = class1.MyAsyncMethod().Result;
Assert.IsTrue(result == "OK");
}
}
被测试的代码:
class Class1
{
public Task<string> MyAsyncMethod()
{
var tcs = new TaskCompletionSource<string>();
MyInnerAsyncMethod()
.ContinueWith(t =>
{
// Never reached if TaskScheduler.FromCurrentSynchronizationContext() is set
tcs.SetResult("OK");
}, TaskScheduler.FromCurrentSynchronizationContext());
return tcs.Task;
}
private Task<string> MyInnerAsyncMethod()
{
var tcs = new TaskCompletionSource<string>();
tcs.SetResult("OK");
return tcs.Task;
}
}
问题是,包含在“ContinueWith”方法中的代码是从未达到过如果我指定“TaskScheduler.FromCurrentSynchronizationContext()”。 如果我删除此参数,延续执行正确...
任何意见或建议?
我想这是因为虽然你已经创建了一个新的DispatcherSynchronisationContext,有运行你的任务是执行上的调度循环中没有实际的线程。
尝试把这个在您的测试开始:
// Create a thread
Thread newWindowThread = new Thread(new ThreadStart( () =>
{
// Create our context, and install it:
SynchronizationContext.SetSynchronizationContext(
new DispatcherSynchronizationContext(
Dispatcher.CurrentDispatcher));
// Start the Dispatcher Processing
System.Windows.Threading.Dispatcher.Run();
}));
礼貌: http://reedcopsey.com/2011/11/28/launching-a-wpf-window-in-a-separate-thread-part-1/
躺在你把我放在正确的方式,谢谢!
我没有改变我的代码进行测试,这里是一个新的执行测试代码按预期工作的:
[TestClass]
public class UnitTest1
{
private ExecutionContext _executionContext;
[TestInitialize]
public void OnSetup()
{
_executionContext = CreateExecutionContext();
SynchronizationContext.SetSynchronizationContext(_executionContext.DispatcherSynchronizationContext);
}
[TestCleanup]
public void OnTearDown()
{
// stops the dispatcher loop
_executionContext.Dispatcher.InvokeShutdown();
}
[TestMethod]
public void TestMethod1()
{
var class1 = new Class1();
var result = class1.MyAsyncMethod().Result;
Assert.IsTrue(result == "OK");
}
/* Helper classes and methods */
private ExecutionContext CreateExecutionContext()
{
var tcs = new TaskCompletionSource<ExecutionContext>();
var mockUIThread = new Thread(() =>
{
// Create the context, and install it:
var dispatcher = Dispatcher.CurrentDispatcher;
var syncContext = new DispatcherSynchronizationContext(dispatcher);
SynchronizationContext.SetSynchronizationContext(syncContext);
tcs.SetResult(new ExecutionContext
{
DispatcherSynchronizationContext = syncContext,
Dispatcher = dispatcher
});
// Start the Dispatcher Processing
Dispatcher.Run();
});
mockUIThread.SetApartmentState(ApartmentState.STA);
mockUIThread.Start();
return tcs.Task.Result;
}
internal class ExecutionContext
{
public DispatcherSynchronizationContext DispatcherSynchronizationContext { get; set; }
public Dispatcher Dispatcher { get; set; }
}
/* ------ */
}