Skip to main content

Using callbacks with Moq to check state

Here is the scenario, I have a method that takes an object, however - nowhere in your CUT (class under test) can you publicly access this object to verify state the state of it. I run into this scenario a lot regarding view models, the view model exposes things that we need to look at and interact with as public properties but anything the user doesn’t interact with or see is private which can make testing a pain. Let’s look at an example of something we can easily test before we get to the problem.

[TestMethod]

public void SaveCommandGetsSetWhenConstructed()

{

//Arrange

var adapterMock = new Mock<INewOrderAdapter>();

adapterMock.Setup(x => x.DeclinedBuyItNowPartNumbers)

.Returns(new List<string>() { "12345" });

var vm = new PartDeclinedViewModel(eventAggregator, adapterMock.Object)

{

SelectedLineItems = new ObservableCollection<DeclineReasons>()

{

DeclineReasons.CONDITION

},

CommentsText = "Testing",

SelectedPartNumber = "12345"

};

//Act (done when the constructor is initialized)

//Assert

Assert.IsNotNull(vm.SaveCommand);

}

So - you have defined SaveCommand in your view model, it’s a public delegate command, I can easily write a test that verifies that I am setting the method when we call the constructor for our class. Look at the test below – it does just that,(there are a few things in the arrange portion of the test that are telling me my view model needs a little refactoring but ignore that for now).

Now that we have looked at that example, what if the method that the delegate command we are using for the SaveCommand calls something that changes a private property? Whatever it is isn’t visible to the user so we don’t have anything that is publicly accessible in the view model. We don’t need it. Except we want to test that our method does the right thing to this private object. We can use a callback to set a value to a variable that is scoped inside the test method and then call our asserts on the state of the object. Let me try to use some more examples.

When we create the view model in the test above you can see that a mock adapter is created. This mock adapter has methods we need to mock out using Mock.Setup(), this of course means we can make them do whatever we want them too. So instead of having adapter.Save(myType, myObject) do whatever it normally does (we aren’t testing that here). We can mock it to say “Take the variable that was passed in and put it in this local variable” – that is what the callback does. See the test below which does just that.

[TestMethod]

public void LineItemIdGetsSetIfExists()

{

//arrange

DeclinedPart declinedPart = new DeclinedPart();

var lineItem = new LineItem() {PartNumber = "12345", LineItemId = 555};

var currentSaleOrder = new CreateSalesOrder();

currentSaleOrder.LineItems = new List<CreateLineItem>() { (CreateLineItem)lineItem };

var adapterMock = new Mock<INewOrderAdapter>();

adapterMock.Setup(x => x.DeclinedBuyItNowPartNumbers)

.Returns(new List<string>() {"12345"});

adapterMock.Setup(x => x.CurrentSalesOrder).Returns(currentSaleOrder);

adapterMock.Setup(x => x.SaveDeclineReason(It.IsAny<DeclinedPart>())).

Callback((DeclinedPart x) => declinedPart = x);

var vm = new PartDeclinedViewModel(eventAggregator, adapterMock.Object)

{

SelectedLineItems = new ObservableCollection<DeclineReasons>()

{

DeclineReasons.CONDITION

},

CommentsText = "Testing",

SelectedPartNumber = "12345"

};

//Act

vm.SaveCommand.Execute();

//Assert

Assert.AreEqual(declinedPart.LineItemId, lineItem.LineItemId);

}

There you have it, now you look at the local variable (the one you created in your test method) and check that your method does what you wanted it to. People will point out that you can use things like private accessors for this task however I tend to shy away from those. They don't always seem to be reliable and they tend to make the tests more confusing - in my opinion of course. at any rate - this is just another nifty little trick for examining the state of something you don't necessarily have direct access to.

Comments

Popular posts from this blog

Unit testing static methods when using Membership and ProfileBase in MVC 4

So you might be thinking that you want to use the Membership class and the ProfileBase class in Microsoft’s System.Web.Security and System.Web.Providers but then you also want to write unit tests as well so you decide to go stand in traffic instead once you are overcome by the plethora of static nonsense that is the design of these two classes. OK, so it isn’t that bad but it is frustrating however there are ways around it and I wanted to try and blog about some of those techniques in the hope that others won’t have to toil with as much frustration as I did when using these classes. Backgound Basically I wanted to find a clean simple way of making use of and extending Microsofts built in forms authentication. It’s easy to use, relatively secure and can save a lot of time and code, well sort of until you want to unit test. The ProfileBase class is great for extending profiles and adding custom properties so you don’t have to introduce a whole lot of redundant code. A good example of

Styling the combox box in WPF

If you want to play with the style of the combo box in WPF the easiest thing to do is use expression blend, drag a combo box control onto you project then click, "Edit Template" -> "Edit a copy"... This will take the entire default template for the combox box and put it into your XAML file. Now go to the XAML and you can grab the entire style and do whatever you like with it... I usually put things like this into a main poject under the solution, something like "shared" is a good name for the project... One thing that is important to note though is that you have to include a reference to the PresentationFramework.Aero assembly cause you will need the Microsoft.Windows.Themes namespace.

Connecting to a HiTechnic prototype board to an Arduino

Connecting to a HiTechnic prototype board to an Arduino. If you are thinking to yourself, “ Wouldn't it be fun to take a prototype board from Hitechnic and connect it to my Arduino? I wonder if it is possible...” Well I am here to tell you that Yes, indeed it is possible, it is not only possible it works rather nicely, of course - HiTechnic doesn’t really support this and the NXT documentation doesn’t have a section called “Cutting a cable in half to connect it your Arduino” so it took a little research to make it it happen which is why I thought I would share this information with the world. Step one - the cable  I took a cable from my mindstorms kit and chopped one end off, I then took some nice stiff jumper wires and soldered them onto the ends so I had something that I could plug into the Arduino.  Step two - What goes where.  So the big question was what pins to plug it into on the Arduino. I have an Uno which means that pins A4 and A5 are the i2c SDA and S