I am attempting to write unit tests for a library that invokes WinForms interface.
The library codes uses BeginInvoke using a Form handle thread safety. This means in my unit testing I need to wait for the for the invoked method to run before checking to see if it worked. After doing some research I thought I could accomplish this by calling Application.DoEvents() after my library call but before I check the result:
logger.Fatal("Test"); // Send log
Application.DoEvents(); // Process events for BeginInvoke to run
Assert.Equal("Fatal NLog.UnitTests.Targets.ToolStripItemTargetTests Test", getText(testForm, testItem)); // Test if method worked.
That worked for the test of my first method call, but if I do a second test that one does not work. For some reason if I do TWO Application.DoEvents() calls then the second will work:
logger.Error("Foo");
Application.DoEvents();
Application.DoEvents();
Assert.Equal("Error NLog.UnitTests.Targets.ToolStripItemTargetTests Foo", getText(testForm, testItem));
This already doesn't make sense to me because Application.DoEvents() documentation states "Processes all Windows messages currently in the message queue" . Unless I'm reading this wrong it shouldn't return the first call until all events have been processed meaning a second call should never be necessary. This shows there is something going on I don't understand. That said I would accept it as a workaround, but putting two calls in does not work for the 3rd-6th tests.
I've tried several other whacky ideas that were not provide enough information to be worth outlining here. You can see them looking at the commits in the above link.
I figure there has to be something about how unit tests are processed by appveyor is causing the WinForms thread/events to not process. How can I wait for BeginInvoke to process in such a context?
The problem is threading related. Not with the WinForms threading/event handling as I thought, but rather with the XUnit runner threading approach.
By adding a new class of tests to an existing project I created a second XUnit collection. XUnit was running these tests in parallel. As the libary being tested only has one global static configuration this resulted in one test pulling the rug out from the other.
By adding a
Collectionattribute at the beginning of my new test class and to the existing test the XUnit running then runs them in sequence and it works as I originally coded it with a singleApplication.DoEvents()causing myBeginInvoked method to process.