views:

99

answers:

1

I've created a unit test that tests interactions on my ViewModel class in a Silverlight application. To be able to do this test, I'm mocking the service interface, injected to the ViewModel. I'm using Moq framework to do the mocking.

to be able to verify bounded object in the ViewModel is converted properly, I've used a callback:


[Test]
public void SaveProposal_Will_Map_Proposal_To_WebService_Parameter()
{
 var vm = CreateNewCampaignViewModel();
 var proposal = CreateNewProposal(1, "New Proposal");

 Services.Setup(x => x.SaveProposalAsync(It.IsAny<saveProposalParam>())).Callback((saveProposalParam p) =>
 {
  Assert.That(p.plainProposal, Is.Not.Null);
  Assert.That(p.plainProposal.POrderItem.orderItemId, Is.EqualTo(1));
  Assert.That(p.plainProposal.POrderItem.orderName, Is.EqualTo("New Proposal"));
 });

 proposal.State = ObjectStates.Added;
 vm.CurrentProposal = proposal;
 vm.Save();
}

It is working fine, but if you've noticed, using this mechanism the Assert and Act part of the unit test have switched their parts (Assert comes before Acting). Is there a better way to do this, while preserving correct AAA order?

+1  A: 

I'm not sure that you've changed the semantics of the AAA order. Consider the execution of the test. Your mocked interface will not be called until the Action invokes it. Therefore, during execution, your program still follows the Arrange, Act, and Assert flow.

The alternative would be to use Data Injection and create an interface between your CampaignViewModel and the web service that it uses. You can then create a class in your UnitTests that saves your parameter information and Assert on that class member/property rather than use Moq to create a proxy on the fly.

Moq should not be used to simulate storage or assignment. Rather, use Moq to provide dummy mechanisms and values to allow your Unit Tests to execute. If Asserting storage is a requirement, then take the time to create a class that will hold on to your values.

villecoder