Imagine a function like this:
private static ConcurrentList
One way to do this is to make your type configurable such that it takes a TaskScheduler
instance.
public MyCollection(TaskScheduler scheduler) {
this.taskFactory = new TaskFactory(scheduler);
}
public void Add(object x) {
taskFactory.StartNew(() => {
list.Add(x);
});
}
Now in your unit tests what you can do is create a testable version of TaskScheduler
. This is an abstract class which is designed to be configurable. Simple have the schedule function add the items into a queue and then add a function to manually do all of the queue items "now". Then your unit test can look like this
var scheduler = new TestableScheduler();
var collection = new MyCollection(scehduler);
collection.Add(42);
scheduler.RunAll();
Assert.IsTrue(collection.Contains(42));
Example implementation of TestableScehduler
class TestableScheduler : TaskScheduler {
private Queue m_taskQueue = new Queue();
protected override IEnumerable GetScheduledTasks() {
return m_taskQueue;
}
protected override void QueueTask(Task task) {
m_taskQueue.Enqueue(task);
}
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) {
task.RunSynchronously();
}
public void RunAll() {
while (m_taskQueue.Count > 0) {
m_taskQueue.Dequeue().RunSynchronously();
}
}
}