0

I am trying to unit test my viewmodel and I have many commands that simply create a new task and call a service method and using a continuation gets the results and binds them to properties on the viewmodel. I'm fairly new to unit testing and not sure how I would test this scenario. Since its running in a task the assert in my test happens before the service call finishes and before I can set any properties on my viewmodel. Is this how i should unit test my viewmodel?

public ICommand GetItems
{
  if(this.Category != null)
  {
    Task<List<Item>> t = new Task<List<Item>>((o) =>
    {
       return _service.GetItems(this.Category);
    }
    t.ContinueWith((task) =>
    {
       this.Items = task.Result;
    }
    t.Start();
  }
}


[TestMethod]
public void TestGetItems()
{
  var selectedCategory = Category.NewItems;
  var expected = new List<Item>(){ new Item(){ Value = "ExpectedValue" } };
  var service = new Mock<IService>();
  service.Setup(i => i.GetItems(selectedCategory)).Returns(expected);
  var sut = new MainViewModel(_service.Object);
  sut.Category = selectedCategory;
  sut.GetItems.Execute(null);
  Assert.AreEqual(expected, sut.Items);
}
  • 1
    Why don't you pull out the work that the command is doing into a synchronous method that the command calls, then test that method? – jamesSampica Jan 23 '14 at 17:04
  • @Shoe is right... that's the way to go. – Sheridan Jan 23 '14 at 17:57
  • 2
    If I do that and the command is the only thing that calls it wouldn't I just set the method to private then? The only reason I'd make it public is to unit test it. But is that reason enough to make the method public? – Nighttrain5150 Jan 23 '14 at 20:33

1 Answers1

0

I recommend creating an Async Command that can abstract out the need for a background task. See here for one example Asynchronous WPF Commands.

If you choose to, you could also modify your OnProperyChanged function to Dispatch property changes to the UI thread.

This pattern has worked for me in the past, and it simplifies the ViewModel code quite a bit.

This way you could test it as you would any other function.

Community
  • 1
  • 1
sky-dev
  • 6,190
  • 2
  • 33
  • 32