MOQ Mothers

Category:UncategorizedTag: , , :

Am I the only one who does this?

I like to use Object Mothers in my test projects, especially when I have a large number of services or entities I need to feed into the things I am testing. For example, if I have a class I am testing that takes a constructor argument, I may set it up in my test like this:

   1: protected override void Arrange()

   2: {

   3:     _recipeController = new RecipeController(new RecipeEntity());

   4: }

Since I probably don’t want to pass in a real RecipeEntity I can obviously mock one. (Also, don’t freak over the fact that I am injecting a single entity into a controller. This isn’t the point of the post.)

   1: protected override void Arrange()

   2: {

   3:     Mock<IRecipeEntity> moqRm = new Mock<IRecipeEntity>();

   4:     _recipeController = new RecipeController(moqRm.Object);

   5: }

And this is all old hat goodness. It turns out that I find I want to mock IRecipeEntity a lot. And because of that, I can put it up in my context class OR I can get the mock through an object mother.

This is especially useful when I need to build up a complex set of dependencies. So without further delay, here is a mother implementation that mocks up a complete entity.

   1: public static class DomainEntityMother

   2:    {

   3:        public static IRecipeEntity Moq_IRecipeEntity()

   4:        {

   5:            Guid id = Guid.NewGuid();

   6:  

   7:            var moq = new Mock<IRecipeEntity>();

   8:                moq.SetupGet(m => m.Id).Returns(id);

   9:                moq.SetupGet(m => m.Title).Returns("Recipe : " + id);

  10:                moq.SetupGet(m => m.CooksNotes).Returns("Notes : " + id);

  11:                moq.SetupGet(m => m.Ingredients).Returns(DomainEntityMother.Moq_IIngredientEntities());

  12:  

  13:  

  14:            return moq.Object;

  15:        }

  16:  

  17:        public static IList<IIngredientEntity> Moq_IIngredientEntities()

  18:        {

  19:            var ingredientEntities = new List<IIngredientEntity>();

  20:                ingredientEntities.Add(Moq_IIngredientEntity());

  21:                ingredientEntities.Add(Moq_IIngredientEntity());

  22:                ingredientEntities.Add(Moq_IIngredientEntity());

  23:                ingredientEntities.Add(Moq_IIngredientEntity());

  24:  

  25:            return ingredientEntities;

  26:        }

  27:  

  28:        private static int ingredientCounter = 0;

  29:  

  30:        public static IIngredientEntity Moq_IIngredientEntity()

  31:        {

  32:            ingredientCounter++;

  33:            Guid id = Guid.NewGuid();

  34:            var moq = new Mock<IIngredientEntity>();

  35:            moq.SetupGet(m => m.Amount).Returns(ingredientCounter.ToString);

  36:            moq.SetupGet(m => m.Unit).Returns("TBSP");

  37:            moq.SetupGet(m => m.Description).Returns("Ingredient : " + id);

  38:            moq.SetupGet(m => m.Id).Returns(id);

  39:            return moq.Object;

  40:        }

  41:  

  42:        public static IList<IRecipeEntity> Moq_IRecipeEntities()

  43:        {

  44:            IList<IRecipeEntity> recipeEntities = new List<IRecipeEntity>();

  45:            for (int i = 0; i < 5; i++)

  46:            {

  47:                recipeEntities.Add(Moq_IRecipeEntity());

  48:            }

  49:            return recipeEntities;

  50:        }

  51:    }

And now my test reads like this:

   1: protected override void Arrange()

   2: {

   3:     _recipeController = new RecipeController(DomainEntityMother.Moq_IRecipeEntity());

   4: }

Now, this is cool, but what if I want to make a bad entity? One that should make my test fail, for instance? Do I need another mother? Nope, I just use the one the mother created, an mess with it a little.

   1: protected override void Arrange()

   2: {

   3:     var moqEntity = Mock.Get(DomainEntityMother.Moq_IRecipeEntity());

   4:         moqEntity.SetupGet(m => m.Id).Returns(Guid.Empty);

   5:     _recipeController = new RecipeController(moqEntity.Object);

   6: }

Now I can create all those boundary condition tests that SHOULD fail by starting with a good entity and then only changing the parts I want to cause to be invalid.

7 thoughts on “MOQ Mothers

  1. I never mock entities, just have a builder/object mother create the real class. If this is too difficult to do then thats a design smell.

  2. I’ve never had a reason to mock an entity and over mocking can lead to brittle tests.

    If I am over mocking a service then I would create a real(?) stub to make the test more readable and less brittle.

  3. Look closer at the Mother class. It is really creating a stub, not a mock. That’s the beauty of MOQ. I would not even think this in Rhino.

    Mocking the entity lets me avoid a dependancy on the project the entity live in, which is perfect. I don’t want my web app or it’s test project to need a dependency on the concrete implementation classes for entities, repos, or services.

  4. It does seem more effective than traditional test stubs, especially for the last point. For abstract/polymorphic entities that is a flexible way to setup tests; Creating real stubs can be a pain because you need to implement the entire interface then if you want to test edge conditions you need to add functionality to the stub or create different stubs. With Moq you can just instruct the stub how to respond.

  5. Very practical. Especially if your entities have private ID setter, which is a common practice. You don’t need to use reflection and so on..

  6. I use object mother factories while I am first creating some interaction tests, such as when I need entity data in an in-memory repository. But, I like to replace those objects later in development, as they become brittle. Your MOQ implementation may reduce some of the brittleness, but also seems to cripple the benefit of a well-known OM when you make the entity details so generic. Your thoughts?

    BTW, when you are back in town, we should talk about automocking containers (using StructureMap’s RhinoAutoMocker). I think that automocking can give you some of the same benefits you are getting from this technique without having to the entire entity stub by hand.

Comments are closed.

Find me

RSS
Facebook
Twitter
LinkedIn

Disclaimer

The opinions and content expressed here are my own and not those of my employer.