Telerik blogs

If you’ve never done Test Driven Development or aren’t even sure what this "crazy TDD stuff” is all about than this is the series for you. Over the next 30 days this series of posts take you from “I can spell TDD” to being able to consider yourself a “functional” TDD developer. Of course TDD is a very deep topic and truly mastering it will take quite a bit of time, but the rewards are well worth it. Along the way I’ll be showing you how tools like JustCode and JustMock can help you in your practice of TDD.

Previous Posts in this Series:  Day 12 – Working with Stubs 

In the last post I introduced you to Stubs and wrote a simple example that returned a canned value for a method based on a parameter. In this short post I’ll show you another feature of stubs that can help ensure that your subbed method is be called correctly.

**Note: In the previous post I inadvertently made the return type of PlaceOrder on OrderService a type of object. This should be a Guid. I’ve updated it for this post and apologize for the inconvenience.

Time For a Code Review

Periodically I like to meet with my team for a brief code review. Some teams have specific code review schedules and some preferred a more ad hoc approach. Either is OK. One of the things I like to base my code review schedule on are specific critical parts of the application that are either complex or that many other parts of the application have to integrate with. Reviewing these helps ensure that complex problems are not over-thought and kept as simple as possible while making sure the whole team is aware (even in general terms) how that piece of functionality works. In cases where a lot of developers will be using the piece of functionality in question, it’s good to have the input of others in the API design and be aware of how that API is evolving.

Another occasion for code reviews is when a new developer is on the team. This could be a newly minted developer fresh out of school or simply someone new to the team. I like to review the first few tasks they perform to ensure that they understand the business problem domain, are familiar with the parts of the application that have already been constructed and verify that they understand and are following the local coding standards. Since many of the readers are new to TDD, this seems like a good time for a code review!

In the previous post we wrote the following business domain logic for the PlaceOrder method of the OrderService class:

 1:  public object PlaceOrder(Guid customerId, ShoppingCart shoppingCart)
 2:         {
 3:             var order = new Order();
 4:  return _orderDataService.Save(order);
 5:         }
 
Pretty simple code. To verify that this meets our current business needs we have a test (which we created before we wrote any business code):
 
 1:         [Test]
 2:  public void WhenUserPlacesACorrectOrderThenAnOrderNumberShouldBeReturned()
 3:         {
 4:  //Arrange
 5:             var shoppingCart = new ShoppingCart();
 6:             shoppingCart.Items.Add(new ShoppingCartItem { ItemId = Guid.NewGuid(), Quantity = 1 });
 7:             var customerId = Guid.NewGuid();
 8:             var expectedOrderId = Guid.NewGuid();
 9:  
 10:             var orderDataService = Mock.Create<IOrderDataService>();
 11:             Mock.Arrange(() => orderDataService.Save(Arg.IsAny<Order>())).Returns(expectedOrderId);
 12:             OrderService orderService = new OrderService(orderDataService);
 13:  
 14:  //Act
 15:             var result = orderService.PlaceOrder(customerId, shoppingCart);
 16:  
 17:  //Assert
 18:             Assert.AreEqual(expectedOrderId, result);
 19:         }

(get sample code)

Our test looks pretty good in that it verifies the functional requirements. As an architect however, I see one thing that I am concerned about. Over the years I’ve worked on a number of applications and performance problems would arise from time to time. There are all kinds of reasons for performance problems, but one of the most common ones I found were duplicated or unnecessary calls to an external resource like a database. A call to a database is relatively slow, especially when compared to an in-memory store or a mock. This makes these kinds of defects difficult to detect in unit tests as there is no real performance penalty since we’re using a mock. As the Architect/Lead Developer/Grand Poobah/whatever of this project I want to ensure that for the above test case that Save on the OrderDataService gets called exactly once. Lucky for us JustMock has a facility to verify that our stub was called a specific number of times.

 1:         [Test]
 2:  public void WhenUserPlacesACorrectOrderThenAnOrderNumberShouldBeReturned()
 3:         {
 4:  //Arrange
 5:             var shoppingCart = new ShoppingCart();
 6:             shoppingCart.Items.Add(new ShoppingCartItem { ItemId = Guid.NewGuid(), Quantity = 1 });
 7:             var customerId = Guid.NewGuid();
 8:             var expectedOrderId = Guid.NewGuid();
 9:  
 10:             var orderDataService = Mock.Create<IOrderDataService>();
 11:             Mock.Arrange(() => orderDataService.Save(Arg.IsAny<Order>()))
 12:                 .Returns(expectedOrderId)
 13:  .OccursOnce();
 14:             OrderService orderService = new OrderService(orderDataService);
 15:  
 16:  //Act
 17:             var result = orderService.PlaceOrder(customerId, shoppingCart);
 18:  
 19:  //Assert
 20:             Assert.AreEqual(expectedOrderId, result);
 21:  Mock.Assert(orderDataService);
 22:         }

(get sample code)

I’ve made a few changes to our test. First, I’ve split the arrangement of the mock (starts on line 11) onto three lines to make it easier to read for this example. I’ve also appended the method OccursOnce to the end of the arrangement. This tell JustMock that my expectation is that this method will execute exactly once. Any other number of executions is an error. I’ve also added a call to Mock.Assert on line 21. This call tells our mock to verify that it’s rules have been followed. In this case we only have one rule; that the Save method must be called exactly one time. If the Save method was called any other number of times this call will fail the test. To demonstrate a failure I am going to comment out the call to Save on line 4 of the business code and have the method return a new Guid.

 1:  public Guid PlaceOrder(Guid customerId, ShoppingCart shoppingCart)
 2:         {
 3:             var order = new Order();
 4:  //return _orderDataService.Save(order);
 5:  return Guid.NewGuid();
 6:         }


I’ve also commented out the Assert.AreEqual on line 20 of my test to ensure that the verification of the mock is the first failure that is discovered. When I run the test it fails and the reason I’m given is that the expected number of calls and actual number of calls do not match (Figure 1):

image

Figure 1 – Save was not called to correct number of times.

JustMock was expecting the method to be called one time (expected range of calls is between one and one.) As you’ll see in future posts we can set upper and lower bound numbers for this range. Since we used OccursOnce the range was one to one.

After replacing the items in my code that I commented out to demonstrate this failure, we should have a passing test (Figure 2):

image

Figure 2 – Our test is passing again.

Summary

Unit tests are excellent ways to test functional requirements, but they are also good for verifying some non-functional aspects of our applications as well. By using some more advanced features of JustMock we’ll be able to verify how our mocked objects are being used, which will allow us to use and verify more complex interactions between the various components of our application. Smart mocking can not only help you eliminate defects in the non-functional aspects of your application before they exist, they can make you ask some hard questions about your design early on. This will save you a lot of pain and time later on. There are many more features of JustMock like the one I demonstrated today and I’ll be spending the next several posts demonstrating them and showing you how they can make your unit tests better.

 

Continue the TDD journey:

JustCode download banner image

JustMock banner


About the Author

James Bender

is a Developer and has been involved in software development and architecture for almost 20 years. He has built everything from small, single-user applications to Enterprise-scale, multi-user systems. His specialties are .NET development and architecture, TDD, Web Development, cloud computing, and agile development methodologies. James is a Microsoft MVP and the author of two books; "Professional Test Driven Development with C#" which was released in May of 2011 and "Windows 8 Apps with HTML5 and JavaScript" which will be available soon. James has a blog at JamesCBender.com and his Twitter ID is @JamesBender. Google Profile

Comments

Comments are disabled in preview mode.