问题
Having coded an extension method (based on GUI update when starting event handler class on separate thread?):
public static class ControlExtensions
{
public static TResult InvokeEx<TControl, TResult> (this TControl control,
Func<TControl, TResult> func)
where TControl : Control
{
if (control.InvokeRequired)
return (TResult)control.Invoke (func, control);
return func (control);
}
}
I've been trying to unit test this method both from a UI thread and a normal thread and I can't seem to be able to achieve that.
Here is the unit test code:
[Test]
public void TestInvokeExWithMethodReturningResultOnOtherThread ()
{
// Prepare
string result = string.Empty;
var form = new Form ();
var thread = new Thread (() =>
{
result = form.InvokeEx (f => f.Text);
});
// Execute
thread.Start ();
thread.Join (1000);
// Verify
Assert.That (result, Is.EqualTo ("Some label"));
}
The test passes but if I set a breakpoint in the InvokeEx method (not the call) I see that Control.InvokeRequired is false resulting in the func method directly called.
Furthermore, now the test fails because result is not set.
Additionally, while stepping through the code I see that the func method is executed on the other thread (as expected) and not on the main thread.
Maybe it is because I do not have a real UI thread since I am executing a unit test? How would I achieve that and all the message pumping?
回答1:
I've been trying different things and I've come up with the following:
[Test]
public void TestInvokeExWithMethodReturningResultOnOtherThread ()
{
// Prepare
string result = string.Empty;
var form = new Form ();
var uiThread = new Thread (() => Application.Run (form));
uiThread.SetApartmentState (ApartmentState.STA);
uiThread.Start();
Thread.Sleep (100);
var thread = new Thread (() => result = form.InvokeEx (f => f.Text));
// Execute
thread.Start ();
thread.Join ();
form.InvokeEx (f => f.Close ());
uiThread.Join ();
// Verify
Assert.That (result, Is.EqualTo ("Some label"));
}
This now works perfectly.
Note that I had to add an overload for InvokeEx for a void method.
来源:https://stackoverflow.com/questions/1362858/how-to-properly-unit-test-calling-ui-method-on-another-thread