Класс MVVM nUnit, который использует фоновый рабочий - PullRequest
1 голос
/ 12 марта 2012

У меня есть класс ниже, я хочу, чтобы юнит-тест:

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
  }
}

Вот мой модульный тест:

[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");
}

Проблема в том, что после вызова _worker.RunWorkerAsync () модульное тестирование продолжается и не ожидает асинхронного результата, поэтому данные не готовы.

Я попытался добавить вызов Thread.Sleep перед Assert , но похоже, что это вызывает рабочий worker_RunWorkerCompleted в другом потоке. Из-за этого, когда вызывается UpdateData, я получаю исключение, потому что поток, отличный от потока, создавшего коллекцию, пытается изменить его.

"This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread."

Как я могу проверить этот код? Можно ли это сделать, если я не могу изменить сам класс?

Спасибо.

1 Ответ

4 голосов
/ 12 марта 2012

Вам нужно добавить ManualResetEvent, чтобы сигнализировать о завершении фоновой работы, которую потребители могут подключить к

public class MyClass
{
  ManualResetEvent _doneEvent = new ManualResetEvent(true);
  ...

  public ManualResetEvent BackgroundWorkComplete {
    get { return _doneEvent; }
  }

  void LoadProducts() {
    _doneEvent.Reset();  
    _worker.DoWork += worker_DoWork;
    _worker.RunWorkerCompleted += worker_RunWorkerCompleted;
    _worker.RunWorkerAsync();
  }  

  void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
    UpdateData();
    _doneEvent.Set();
  }
}

Теперь вы можете ждать этого события из кода модульного теста.

_myClass.BackgroundWorkComplete.WaitOne();
Assert.AreEqual(_myClass.Data.Count, 100, "Data item counts do not match");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...