Showing posts with label Moq. Show all posts
Showing posts with label Moq. Show all posts

Friday, 18 October 2013

Arranging Extension Methods

I like to arrange my extension methods in categories based on the functionalities and also to design them to be easily tested (mocked) as described on this post.

That way the methods are grouped nicely and also displayed neatly when showed by intellisense. Below is an example of how I do that:
public interface ICategoryOne
{
 string MethodOne();
 int MethodTwo();
 int MethodThree(string value);
}

internal class RealCategoryOne : ICategoryOne
{
 private StringBuilder sb;

 public RealCategoryOne(StringBuilder sb)
 {
  this.sb = sb;
 }

 public string MethodOne()
 {
  return "method one";
 }

 public int MethodTwo()
 {
  return sb.GetHashCode();
 }

 public int MethodThree(string value)
 {
  return value.Count();
 }
}

public static class MyExtensionMethods
{
 public static Func<StringBuilder, ICategoryOne> CategoryOneFactory = sb => new RealCategoryOne(sb);

 public static ICategoryOne CategoryOne(this StringBuilder sb)
 {
  return CategoryOneFactory(sb);
 }
}  

With intellisense, the methods will be shown like:



Then to test these extension methods with Moq:
Mock<ICategoryOne> categoryOne = new Mock<ICategoryOne>();
categoryOne.Setup(c => c.MethodOne()).Returns("Moq method 1");
categoryOne.Setup(c => c.MethodTwo()).Returns(-555);
categoryOne.Setup(c => c.MethodThree(It.IsAny<string>())).Returns(-999);

StringBuilder sb = new StringBuilder();

MyExtensionMethods.CategoryOneFactory = prm => categoryOne.Object;

var test = sb.CategoryOne().MethodOne();
Assert.AreEqual(test, "Moq method 1");

Alternatively we can create a fake/dummy class for testing:
public class FakeCategoryOne : ICategoryOne
{
 private StringBuilder sb;

 public FakeCategoryOne(StringBuilder sb)
 {
  this.sb = sb;
 }

 public string MethodOne()
 {
  throw new NotImplementedException();
 }

 public int MethodTwo()
 {
  throw new NotImplementedException();
 }

 public int MethodThree(string value)
 {
  throw new NotImplementedException();
 }
}
Then we change the factory above as:
MyExtensionMethods.CategoryOneFactory = prm => new FakeCategoryOne(prm);


Reference:
http://blogs.clariusconsulting.net/kzu/how-to-mock-extension-methods/

Friday, 17 May 2013

Modifying Passed Object to a Mocked Interface's Method

For instance we have a mockable interface with a method accepting an object that modifies its property inside without returning back the new property value. The new value however is required by subsequence codes. For example:
public void InsertOrUpdate(Invoice invoice)
{
   . . .
   context.Add<Invoice>(invoice); // this method will save to database and generate an Id
   
   int generatedId = invoice.InvoiceId; // the Id is required for subsequence codes
   . . .
}
Now how do we do this in our unit test with Moq? We can use Callback feature to modify the object passed then go on with our testing:
// Arrange
Mock<IDomainContext> context = new Mock<IDomainContext>();
InvoiceDS invoiceDS = new InvoiceDS(context.Object);
  //set up so that after context.Add<Invoice>(invoice) is called, InvoiceId is set to 5
context.Setup(c => c.Add<Invoice>(It.IsAny<Invoice>())).Callback<Invoice>(i => i.InvoiceId = 5);
Invoice invoice = new Invoice();

// Act
invoiceDS.InsertOrUpdate(invoice);

// Assert
. . .

Friday, 5 April 2013

Moq - Checking the Order of Methods Called

Say we have codes like below that call two methods:
public void InsertOrUpdate(ItemDto itemDto)
{
    . . .
 context.Add<Item>(item);
 context.SaveChanges();
    . . .
}

We would like to ensure that a method is called after the other. We can use the Callback feature in Moq and a collection type to store predefined values for each method. Then we can check the values stored in the collection and their orders to determine that the methods were called in sequence.
[Fact]
public void SaveChanges_method_is_called_after_Add_method()
{
    // Arrange
    List<string> invokes = new List<string>();
    string addMethod = "Add";
    string saveChangesMethod = "SaveChanges";
    context.Setup(c => c.Add<Item>(It.IsAny<Item>()))
           .Callback(() => invokes.Add(addMethod));
    context.Setup(c => c.SaveChanges())
           .Callback(() => invokes.Add(saveChangesMethod));
            
    // Act
    itemDS.InsertOrUpdate(itemDto);
               
    // Assert
    Assert.Equal(invokes[0], addMethod);
    Assert.Equal(invokes[1], saveChangesMethod);
}

Thursday, 28 February 2013

Checking Parameter Passed to a Method with Moq

Say we are using TDD and would like to add more business logic to the method below. We would like to make sure that the object's created and updated time should be set with current time.
public void Add(Item item)
{        
    // set item created time

    // set item updated time 

    repository.Add(item);
}

Moq provides some argument checking methods that we can use; there are:
- It.Is<Type>(...) ,
- It.IsInRange<Type>(...) and
- It.IsRegex(...)

Below is a unit test using one of the methods; It.Is<Type>(o => checking_condition)
[Fact]
public void Created_time_should_be_set_as_current_time()
{
    // Arrange
    var item = new Item(); 
    var timeToCompare = DateTime.Now.AddHours(-1);

    // Act
    itemDS.Add(item);

    // Assert
    repository.Verify(c => c.Add(It.Is<Item>(i => i.CreatedAt.CompareTo(timeToCompare) > 0)));
}
or we can write like this:
[Fact]
public void Created_time_should_be_set_as_current_time()
{
    // Arrange
    var item = new Item(); 
    var timeToCompare = DateTime.Now.AddHours(-1);
    repository.Setup(c => c.Add(It.Is<Item>(i => i.CreatedAt.CompareTo(timeToCompare) > 0)));

    // Act
    itemDS.Add(item);

    // Assert
    repository.VerifyAll();
}
Run the test. It will fail. Then we can put the code item.CreatedAt = DateTime.Now; on the method. Run the test again. It should pass now.

Now we want to create a test to make sure updated time is set. We will use another way to check the parameter passed to a method. We will use Callback feature to retrieve the parameter. We cannot put a checking conditional logic in Callback argument. However we can assign the passed parameter to an existing object or add it to an existing collection then later we can inspect it.

[Fact]
public void Updated_time_should_be_set_as_current_time()
{
    // Arrange
    var item = new Item(); 
    var timeToCompare = DateTime.Now.AddHours(-1);

    // repository.Setup(c => c.Add(It.Is<Item>(i => i.UpdatedAt.CompareTo(timeToCompare) > 0)));
    // alternate way by using Callback
    repository.Setup(c => c.Add(It.IsAny<Item>())).Callback<Item>(i => item = i);

    // Act
    itemDS.Add(item);

    // Assert
    // repository.VerifyAll();
    // now we are using Callback
    Assert.True(item.UpdatedAt.CompareTo(timeToCompare) > 0);
}

Just for a note, if required, Callback can be combined with Returns function as well. For example:
mock.Setup(. . .)
    .Returns(. . .)
    .Callback(. . .)

mock.Setup(. . .)
    .Callback(. . .)
    .Returns(. . .)
    .Callback(. . .)

Run the test. It will fail. Put the code item.UpdatedAt = DateTime.Now; Now the test will pass.

Our updated method now is
public void Add(Item item)
{        
    // set item created time
    item.CreatedAt = DateTime.Now;

    // set item updated time 
    item.UpdatedAt = DateTime.Now;

    repository.Add(item);
}

References:
http://code.google.com/p/moq/wiki/QuickStart
http://stackoverflow.com/questions/3269717/moq-how-to-get-to-a-parameter-passed-to-a-method-of-a-mocked-service

Saturday, 30 June 2012

xUnit Examples of Testing Controller Actions

We will see some examples of unit tests using xUnit testing framework to test controller actions. Let say we have these controller actions:
public ViewResult Add()
{            
    return View("Add", new StuffViewModel());
}


[HttpPost]
public ActionResult Add(StuffViewModel stuffViewModel)
{
    if (ModelState.IsValid)
    {
        Stuff stuff = mappingService.Map<StuffViewModel, Stuff>(stuffViewModel);
        stuffRepository.InsertOrUpdate(stuff);
        return RedirectToAction("List");
    }
    return View("Add", stuffViewModel);
}
As you can see both actions use same view. The first action is for displaying the view (HTTP GET) and the other is for handling submission from the view (HTTP POST).

Then below are the unit tests to cover both actions functionalities:
public class Add
{
    private Mock<IStuffRepository> stuffRepository;
    private Mock<IMappingService> mappingService;
    private StuffsController controller;

    public Add()
    {
        stuffRepository = new Mock<IStuffRepository>();
        mappingService = new Mock<IMappingService>();
        controller = new StuffsController(stuffRepository.Object, mappingService.Object);
    }


    [Fact]
    public void GET_should_return_add_view()
    {
        // Arrange

        // Act
        var result = controller.Add();

        // Assert
        var viewResult = Assert.IsType<ViewResult>(result);
        Assert.Equal("Add", viewResult.ViewName);
    }

    [Fact]
    public void GET_should_have_StuffViewModels()
    {
        // Arrange

        // Act
        var result = controller.Add();

        // Assert
        //Assert.IsAssignableFrom<StuffViewModel>(result.ViewData.Model); 
        Assert.IsType<StuffViewModel>(result.ViewData.Model);
    }

    [Fact]
    public void POST_should_save_to_database_if_model_is_valid()
    {
        // Arrange
        StuffViewModel stuffViewModel = new StuffViewModel { StuffID = 1 };
        Stuff stuff = new Stuff { StuffID = 1};
        mappingService.Setup(m => m.Map<StuffViewModel, Stuff>(It.IsAny<StuffViewModel>()))
                        .Returns(stuff);
                
        // Act
        controller.Add(stuffViewModel);

        //Assert
        stuffRepository.Verify(o => o.InsertOrUpdate(stuff), Times.Once());
    }

    [Fact]
    public void POST_should_redirect_to_list_view_after_saving()
    {
        // Arrange
        StuffViewModel stuffViewModel = new StuffViewModel { StuffID = 1 };
        Stuff stuff = new Stuff { StuffID = 1 };
        mappingService.Setup(m => m.Map<StuffViewModel, Stuff>(It.IsAny<StuffViewModel>()))
                        .Returns(stuff);

        // Act
        var result = controller.Add(stuffViewModel);

        // Assert
        var redirectToRouteResult = Assert.IsAssignableFrom<RedirectToRouteResult>(result);
        Assert.Equal("List", redirectToRouteResult.RouteValues["action"]);
    }

    [Fact]
    public void POST_if_not_valid_should_not_save_into_database()
    {
        // Arrange
        StuffViewModel stuffViewModel = new StuffViewModel { StuffID = 1 };
        Stuff stuff = new Stuff { StuffID = 1 };
        mappingService.Setup(m => m.Map<StuffViewModel, Stuff>(It.IsAny<StuffViewModel>()))
                        .Returns(stuff);
        controller.ModelState.AddModelError("key", "error");

        // Act
        var result = controller.Add(stuffViewModel);

        // Assert
        stuffRepository.Verify(o => o.InsertOrUpdate(stuff), Times.Never());
    }

    [Fact]
    public void POST_if_not_valid_should_return_to_add_view()
    {
        // Arrange
        StuffViewModel stuffViewModel = new StuffViewModel { StuffID = 1 };
        Stuff stuff = new Stuff { StuffID = 1 };
        mappingService.Setup(m => m.Map<StuffViewModel, Stuff>(It.IsAny<StuffViewModel>()))
                        .Returns(stuff);
        controller.ModelState.AddModelError("key", "error");

        // Act
        var result = controller.Add(stuffViewModel);

        // Assert
        var viewResult = Assert.IsType<ViewResult>(result);
        Assert.Equal("Add", viewResult.ViewName);
    }

    [Fact]
    public void POST_if_not_valid_should_return_view_with_StuffViewModel()
    {
        // Arrange
        StuffViewModel stuffViewModel = new StuffViewModel { StuffID = 1 };
        Stuff stuff = new Stuff { StuffID = 1 };
        mappingService.Setup(m => m.Map<StuffViewModel, Stuff>(It.IsAny<StuffViewModel>()))
                        .Returns(stuff);
        controller.ModelState.AddModelError("key", "error");

        // Act
        var result = controller.Add(stuffViewModel);

        // Assert
        var viewResult = Assert.IsType<ViewResult>(result);
        Assert.IsType<StuffViewModel>(viewResult.ViewData.Model);
    }
}

Thursday, 21 June 2012

Mocking AutoMapper in Unit Testing

This post will show how to mock AutoMapper with Moq in unit testing. Unit testing that has dependency to AutoMapper would require all of the mapping configurations be specified and run first before the actual mapping takes place (Mapper.Map(...) is called). These configurations would be burdensome and should not be included in unit testing. A unit test for a feature should only test that particular feature the developer has written. It should not test other services or functionalities. This is where the concept of mocking come up.

To be able to mock AutoMapper, we can use Dependency Injection to inject a mapper interface to the constructor of the calling code's class rather than using AutoMapper directly. Below is an example of such interface:
public interface IMappingService
{
    TDest Map<TSrc, TDest>(TSrc source) where TDest : class;
}

Then create an implementation class for the interface. Note on line 5 that for this class we specify AutoMapper directly.
public class MappingService : IMappingService
{
    public TDest Map<TSrc, TDest>(TSrc source) where TDest : class
    {
        return AutoMapper.Mapper.Map<TSrc, TDest>(source);
    }
}

Next, bind the interface with the concrete class. Below is an example of how to do it with Ninject:
kernel.Bind<IMappingService>().To<MappingService>();

Then whenever we want to do mapping, we call the interface's Map method instead of using the AutoMapper's Mapper.Map() method.
public ViewResult List()
{
    IEnumerable<Stuff> stuffs = stuffRepository.All;

    List<StuffViewModel> model = mappingService.Map<IEnumerable<Stuff>, List<StuffViewModel>>(stuffs);

    return View("List", model);
}
Please remember that mapping configurations need to be specified first before we could do any mapping. You can see this post to see how to set up the configurations.

Now we can mock the mapper in our unit test. In the example below I use xUnit testing framework. As you can see; first we create a mock instance from the interface, setup what the Map method will return and then pass the mock object to the class constructor of the feature to be tested (line 6, 25 and 28).
[Fact]
public void ListPageReturnsStuffViewModels()
{
    // Arrange
    Mock<IStuffRepository> stuffRepository = new Mock<IStuffRepository>();
    Mock<IMappingService> mappingService = new Mock<IMappingService>();

    List<Stuff> stuffs = new List<Stuff>();
    stuffRepository.Setup(r => r.All).Returns(stuffs.AsQueryable());

    var viewModelStuffs = new List<StuffViewModel> {
        new StuffViewModel { StuffID = 1/*,
                                Name= "Bip",
                                Description= "Colourful baby bip",
                                DateAdded = DateTime.Now,
                                UserID = 1 */
        },
        new StuffViewModel { StuffID = 2/*,
                                Name= "Socks",
                                Description= "Winter socks with animal figures",
                                DateAdded = DateTime.Now,
                                UserID = 1 */
        }
    };
    mappingService.Setup(m => m.Map<IEnumerable<Stuff>, List<StuffViewModel>>(It.IsAny<IEnumerable<Stuff>>()))
                    .Returns(viewModelStuffs);

    var controller = new StuffsController(stuffRepository.Object, mappingService.Object);


    // Act
    var result = controller.List() as ViewResult;
    //var model = result.ViewData.Model as List<StuffViewModel>;


    // Assert
    var model = Assert.IsType<List<StuffViewModel>>(result.ViewData.Model);
    Assert.Equal(2, model.Count);                
}