I have the below class I want to unit test:
public class MyClass
{
BackgroundWorker _worker = new BackgroundWorker();
ObservableCollection<Product> _data = new ObservableCollection<Product>();
public MyClass()
{
LoadProducts();
}
public ObservableCollection<Product> Data
{
get
{
return _data;
}
}
void LoadProducts()
{
_worker.DoWork += worker_DoWork;
_worker.RunWorkerCompleted += worker_RunWorkerCompleted;
_worker.RunWorkerAsync();
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
UpdateData();
}
void UpdateData()
{
_data.Clear();
//Do some work with the retrieved products
}
}
Here is my unit test:
[SetUp]
public void Setup()
{
_myClass = new MyClass();
}
[Test]
public void Data_Count_Should_Contain_Same_Number_Of_Items_As_Source()
{
Assert.AreEqual(_myClass.Data.Count, 100, "Data item counts do not match");
}
The problem is that once _worker.RunWorkerAsync() is called, the unit test continues and does not wait for the async result so the data is not ready.
I tried adding a Thread.Sleep call before the Assert, but it looks like that causes worker_RunWorkerCompleted to be called on another thread. Because of that, when UpdateData is called, I get an exception because a thread other than the thread that created the collection is trying to modify it.
"This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread."
How can I test this code? Is it possible to do if I cannot change the class itself?
Thanks.
You need to add a
ManualResetEventto signal the completion of the background work which consumers can hook intoNow you can wait on this event from the unit test code.