Coding and Dismantling Stuff

Don't thank me, it's what I do.

About the author

Russell is a .Net developer based in Lancashire in the UK.  His day job is as a C# developer for the UK's largest online white-goods retailer, DRL Limited.

His weekend job entails alternately demolishing and constructing various bits of his home, much to the distress of his fiance Kelly, 3-year-old daughter Amelie, and menagerie of pets.

TextBox

  1. Fix dodgy keywords Google is scraping from my blog
  2. Complete migration of NHaml from Google Code to GitHub
  3. ReTelnet Mock Telnet Server à la Jetty
  4. Learn to use Git
  5. Complete beta release FHEMDotNet
  6. Publish FHEMDotNet on Google Code
  7. Learn NancyFX library
  8. Pull RussPAll/NHaml into NHaml/NHaml
  9. Open Source Blackberry Twitter app
  10. Other stuff

Moq asserts - .Verify() vs .VerifyAll() and how VerifyAll can seriously hamper test readability

Hi all,

I've been looking at some tests we've been writing here today, and I think I've spotted a bit of an anti-pattern that I'd like to quickly draw out. In my experience, when I pick up existing unit tests there are three things I look at - what code is being exercised, do the tests pass when I run them, and crucially what is being asserted. Your assert is the one line of code that justifies te existene of the entire test. Getting this wrong can lead to a situation where even if you have 100% code coverage, you have no assurance that your code actually does anything useful at all.

The problem test in question:

 

public void MakeTea_WithMilk_TeaBagIsDunked()
{
  var mockTeabag = new Mock<ITeabag>();
  mockTeabag.Setup(x => x.Dunk()).Verifiable();
  
  var teaProvider = new TeaProvider(mockTeabag.Object);
  teaProvider.Provide();

  mockTeabag.VerifyAll();
}

 

The first thing I'd recommend is the addition of the "Arrange", "Act" and "Assert" comments to break up the test (though I get that's probably a very personal preference!).  But more importantly, what is being asserted against?  What does "VerifyAll" tell us?  Since our setup isn't setting up a response, and our mock behavious isn't set as strict, the same test can be written as follows and should be a lot clearer:

public void MakeTea_WithMilk_TeaBagIsDunked()
{
  // Arrange
  var mockTeabag = new Mock<ITeabag>();
  
  // Act
  var teaProvider = new TeaProvider(mockTeabag.Object);
  teaProvider.Provide();

  // Assert
  mockTeabag.Verify(x => x.Dunk());
}
It's now obvious that the one thing this test is asserting is that the mock teabag has been "Dunk"ed.  Under the hood, Moq is apparently listening to all interactions and simply storing them away, so that we can dig in after the event.

Caveat - I haven't tested the code above, so copy-and-pasting into your own beverage provision products is at your own risk!  But the general principle is tested.

Russ


Permalink | Comments (0)

Add comment

  Country flag

biuquote
  • Comment
  • Preview
Loading