Unit testing facilitation in .NET application development: MOQ Framework

This article concentrates on mocking framework Moq as great tool for unit testing. It overviews various facilities of Moq on concrete functionality samples and unit tests written with the help of this mocking framework.

.NET development: Using Moq Framework for unit testing

Explanation of “What is Moq” you can find here. I will just give it in short.

Moq is mocking library for .NET. It takes full advantage of .NET 3.5 (i.e. Linq expression trees) and C# 3.0 features (i.e. lambda expressions) that make it the most productive, type-safe and refactoring-friendly mocking library available. And it supports mocking interfaces as well as classes. It is extremely simple and straightforward, and doesn't require any prior knowledge or experience with mocking concepts.

Start of works with MOQ

In order to begin using Moq you will require moq.dll (you can download it from this indirect link). After you download it and reference to your testing project you can start using it. Quick start samples you can find here and I think they would provide you with more than enough information to begin testing.

But from my side I want to give you few advices and deeper level samples which I got when tried to resolve various problems during development and testing. Anyway I should give some easy samples, so that my next article would be consistent.

Let’s consider that we have next User model and manager interfaces (IUserManager and INotificationManager) which interact with such model.

public class User  {      public int Id { get; set; }     public string Name { get; set; }     public string Area { get; set; } }  public interface INotificationManager {      void Notify(User user);      void Notify(User user, string key); }  public interface IUserManager {      User Find(string name, string area);     void Save(User user);      bool Delete(User user);  }

 

And UserService which serves some logic using both manager interfaces:

 UserService(IUserManager userManager, INotificationManager notificationManager)

 

I would strongly recommend use interfaces so this will make code more flexible and implementation independent but using mocking you may get deeper into internals of logic you test. This does not mean that Moq could not mock concrete class method. For such case you just need to make public method modifier virtual. Anyway testing of systems built with use of IoC/DI patterns and loose object coupling with Moq look and work very organically.

Enough with talking and continue with testing. Let’s start with testing method of UserService:

public User LoadAndPreset(string name, string newName, string area) {      //searching by old name      var user = _userManager.Find(name, area);      //and preset new      user.Name = newName;      return user;  }

 

As you can see we are searching for user by name and area and then updating name of found user to specified new value. So best (and one for this situation) candidate to be mocked is IUserManager.Find because in the real it would access to database or other storage where users are and it would be complicated and/or time consuming to execute/prepare in the test over real data access or so.

Before start testing let’s initialize mock objects:

 [TestFixture]  public class UserServiceTests {      private Mock<IUserManager> _userManagerMock = new Mock<IUserManager>();     private Mock<INotificationManager> _notificationManagerMock = new Mock<INotificationManager>();     private UserService _service;       [SetUp]      public void setup()      {          _userManagerMock = new Mock<IUserManager>();          _notificationManagerMock = new Mock<INotificationManager>();         _service = new UserService(_userManagerMock.Object,   _notificationManagerMock.Object);     }

 

The following test checks correctness of service method execution:

 [Test]  public void LoadAndPresetTest() {      //this user object we wish method Find to return      var user = new User()                  {                      Name = "old name",                      Area = "area"                  };      //setting up expectaion and value method should return       _userManagerMock.Setup(m => m.Find("old name", "area"))         .Returns(user);       //service method call      var res = _service.LoadAndPreset("old name", "new   name", "area");      //check if logic is correct      Assert.IsNotNull(res);      Assert.AreEqual("new name", res.Name);  }

 

So what we defined with Moq? Actually we said that we would expect IUserManager.Find to be called with parameters “old value” and “area” and if method will be called with such parameters it should return object of type User defined by us.

Note that parameters with which you call method should be equal to parameters you passed into method setup.

Following sample shows such situation:

 var user1 = new User();  var user2 = new User();  _userManagerMock.Setup(m => m.Delete(user1))      .Returns(true);  _service.DeleteUser(user2);

 

Mocked method will not be called because user1 is not equal to user2 and by default mocking behavior (Mock.Behavior==Loose) mocked IUserManager.Delete will return false (which is actual default(T)). You may set Mock.Behavior to Strict if you want to be notified with exception about not set up method was called. But for the case of loose mock behavior we may check if our mocked method was called by Mock.VerifyAll (actually it will check for each setup) so if we put _userManagerMock.VerifyAll() after service method call we will get exception saying that not all setup methods called.

For the cases when you cannot specify exactly same parameter value to method setup you may use one of

 It.Is<T>(Expression<Predicate<T>>), It.IsAny<T>(T), It.IsRegex<T>(string), It.IsInRange<T>(T,T). _userManagerMock.Setup(m => m.Find("old name", It.IsAny<string>())); _userManagerMock.Setup(m => m.Find("old name", It.Is<string>(s => s == "area")));  _userManagerMock.Setup(m => m.Find("old name", It.IsRegex(".*rea")));

 

And back again to loose coupling. Let’s look on next situation:

public User FindForCurrentArea(string name) {      var obj = findUserForCurrentAria(name);      return obj;  }  private User findUserForCurrentAria(string name) {      var obj = _userManager.Find(name, CURRENT_AREA);      return obj;  }

 

We cannot access to private method and as result mock it but we still can mock IUserManager.Find.

 [Test]  public void FindForCurrentAreaTest() {      var user = new User()      {          Name = "name",          Area = UserService.CURRENT_AREA      };      _userManagerMock.Setup(m => m.Find("new name", UserService.CURRENT_AREA))         .Returns(user);       var res = _service.FindForCurrentArea("name");       Assert.IsNotNull(res);      Assert.AreEqual("name", res.Name);      Assert.AreEqual(UserService.CURRENT_AREA, res.Area);  }

 

Actually this is easy simple private method but in the real application such method will have more complex structure but we still have control over testing method logic by having source data using which we can get end result we expect.

Next sample demonstrates callback functionality of mocked object. Consider that we are loading user and updating his name and we want to see if information stored on user is correctly updated:

public void Update(string name, string newName) {      var obj = findUserForCurrentAria(name);      obj.Name = newName;       _userManager.Save(obj);  }

 

And test:

 [Test]  public void UpdateTest()  {      var user = new User()      {          Name = "old name",          Area = UserService.CURRENT_AREA      };      _userManagerMock.Setup(m => m.Find("old name", UserService.CURRENT_AREA))         .Returns(user);      _userManagerMock.Setup(m => m.Save(user))          .Callback((User u) =>                      {                          Assert.AreEqual("new name", u.Name);                     });       _service.Update("old name", "new name");      _userManagerMock.VerifyAll();  }

 

Callback method will provide us with access inside method we setup. I usually use it to ensure correctness of passed parameters. It can execute any logic you will require in the test. We will try to show you that by the next sample.

Consider that we create a new user with passed name, saving it to storage (after he stored he got unique identity) and generate some secret key and going to notify user with it. Problem is in that we neither have access to new user nor know his identity.

public void CreateAndNotify(string name) {      private var user = new User()                            {                                 Name = name,                                 Area = CURRENT_AREA                             };       //lets say that Save method saving new object to database and      //setting identifier to this object       _userManager.Save(user);       string key = string.Format("{0}_{1}", user.Id, user.Name);      _notificationManager.Notify(user, key);  }

 

So let’s look how test solves that.

 [Test]  public void CreateAndNotify() {      var user = new User()      {          Name = "name",          Area = "area"      };      _userManagerMock.Setup(m => m.Find("name", "area"))         .Returns(user);      _userManagerMock.Setup(m => m.Save(It.IsAny<User>()))          .Callback((User u) =>                      {                          u.Id = 99;                      });       _notificationManagerMock.Setup(m => m.Notify(It.IsAny<User>(), It.IsAny<string>()))         .Callback((User u, string key) =>          {              Assert.AreEqual(99, u.Id);              Assert.AreEqual("name", u.Name);              Assert.AreEqual(UserService.CURRENT_AREA, u.Area);              Assert.AreEqual("99_name", key);          });       _service.CreateAndNotify("name");       _notificationManagerMock.VerifyAll();  }

 

As you can see callback of IUserManager.Save emulates generation of identity of User object which is available in the test so we got complete object which was created inside method. Now we can check correctness of generated key. Negative side of last two tests is that they actually break “Arrange-Act-Assert” pattern and test became not very clear.

Conclusions

Moq is powerful and useful instrument for testing. If after refactoring signature of method you mocked in the test you will be notified about that at compile time and test stays green. But as you may notice if we are testing deeper and deeper method logic we have to provide full chain of methods called inside it. So as a result our test became closely dependent to the internals of the method we test and if we refactor internals test may become red. Actually it is not problem of Moq it is problem of all(?) mocking systems. And other unpleasant thing which is coming from first problem is that preparation can become greater then assertion part. Anyway mocking will not give you 100% proof that in the real world the method will work as expected and it Moq should not. This lies on the shoulders of the tester. This and other benefits and negative points are expressed in the article of David Cazzulino.

I also attached solution with samples here.

 

Alexey V.
.Net team, Binary Studio

Post your comment

  • Comment

Contact:


Skype call: My status binary_studio
E-mail: info@binary-studio.com

Quick Navigation:


Software Development Company
Microsoft Development Services

Our clients say:


We did our first project with Binary Studio in remote 2005. Since then we’ve completed many projects most of which were implemented on .Net platform and also few corporate solutions on base of Microsoft SharePoint Server.

Mr. Mika Ahorinta (Head of Product Development, "QCGS", Helsinki, Finland)
Install MS Silverlight to have the original view.

Blog:


Creating validation in ASP.NET MVC ...
Software estimations in outsourcin...
How to work with AJAX log updater
Working with Adobe FrameMaker | Bin...
Applied C# Xml Documentation | Bina...

News:


Binary launches new site using Graf...
Binary Studio takes part in the BBC...
Binary's developent office moved to...
New VP in Binary | Binary Studio - ...
Binary opens an office in Czech Rep...

LiveZilla Live Help