AnandhaSundari M
AnandhaSundari M

Reputation: 1108

Mocking using Moq in c#

I have the following code:

public interface IProductDataAccess
{
    bool CreateProduct(Product newProduct);
}

Class ProductDataAccess implements that interface.

public class ProductBusiness
{
    public bool CreateProduct(Product newProduct)
    {
        IProductDataAccess pda = new ProductDataAccess();
        bool result = pda.CreateProduct(newProduct);
        return result;
    }
}

In this case, how to create unit test for CreateProduct method by mocking the IProductDataAccess interface? I thought of having an public instance of IProductDataAccess within ProductBusiness and initialize it using Mock<IProductDataAccess> object but it is not a good practice to expose the data access to the UI layer. Can any one help me?

Upvotes: 32

Views: 80018

Answers (4)

Amol
Amol

Reputation: 4027

Classic example which demonstrates that if you cannot unit test a particular component, REFACTOR it!

This is why I love what any mocking framework enforces you to do - write decoupled code.

In your example, the ProductBusiness class is tightly coupled with the ProductDataAccess class. You could decouple it using (like most of the answers suggest) dependency injection. By doing so, you would end up depending on the IProductDataAccess abstraction and not on any concrete implementation of it.

Another point to note, when you are writing tests/specifications for the business layer, you would typically want to test the "behavior" and not the "state". So, although you could have asserts that verify if "true" was returned, your tests should really test if the expected data access calls that were set using MOQ were actually executed using the .Verify API of MOQ.

Try adding behavior tests where you expect an exception to be thrown (using the ".Throws" API) by the data access layer and check if you need any special handling at the business layer.

Like Kevin suggests, the following implementation of ProductBusiness will work:

public class ProductBusiness
{
  private readonly IProductDataAccess  _productDataAccess;

  public ProductBusiness(IProductDataAccess productDataAccess)
  {
      _productDataAccess = productDataAccess;
  }

  public bool CreateProduct(Product newProduct)
  {
    bool result=_productDataAccess.CreateProduct(newProduct);
    return result;
  }
}

and use any xunit testing framework to write the test as:

 var mockDataAccess = new Mock<IProductDataAccess>();
 mockDataAccess.Setup(m => m.CreateProduct(It.IsAny<Product>())).Returns(true);
 var productBusiness = new ProductBusiness(mockDataAccess.Object);
 //behavior to be tested

Upvotes: 49

Kevin Holditch
Kevin Holditch

Reputation: 5303

With the way that you have currently designed your ProductBusiness class there is no way of changing the IProductDataAccess implementation using a mock. A recommended pattern for this is where you take the dependencies of a type through the constructor. So your class becomes:

public class ProductBusiness
{
  private readonly IProductDataAccess  _productDataAccess;

  public ProductBusiness(IProductDataAccess productDataAccess)
  {
      _productDataAccess = productDataAccess;
  }

  public bool CreateProduct(Product newProduct)
  {
      bool result = _productDataAccess.CreateProduct(newProduct);
      return result;
  }
}

Now you are in a position to test your class by using a mocking framework like . For example:

var mockDataAccess = new Mock<IProductDataAccess>();
mockDataAccess
    .Setup(m => m.CreateProduct(It.IsAny<Product>()))
    .Returns(true);

var productBusiness = new ProductBusiness(mockDataAccess.Object);
// ... test behaviour here

Now you can change how the mock behaves in your setup step and make sure that your CreateProduct method is behaving correctly.

I would also look at a dependency injection framework like . A dependency injection framework can automatically resolve dependencies meaning creating a new type is much easier as you don't have to manually new everything up. Also it means that you can change which implementation is used in one place and it changes everywhere.

Upvotes: 11

Ufuk Hacıoğulları
Ufuk Hacıoğulları

Reputation: 38468

You should inject IProductDataAccess interface as a dependency:

public class ProductBusiness
{
    private IProductDataAccess _productDataAccess;    

    public ProductBusiness(IProductDataAccess productDataAccess)
    {
        _productDataAccess = productDataAccess;
    }

    public bool CreateProduct(Product newProduct)
    {
        bool result = _productDataAccess.CreateProduct(newProduct);
        return result;
    }
}

Then you can replace it with a mock in your tests:

var productDataAccess = new Mock<IProductDataAccess>();
var productBusiness = new ProductBusiness(productDataAccess.Object);

Upvotes: 25

dcastro
dcastro

Reputation: 68660

You shouldn't instantiate a concrete ProductDataAccess inside your CreateProduct method. Instead, IProductDataAccess should be an injectable dependency. This can be done in one of two ways:

Property injection:

public class ProductBusiness
{
    IProductDataAccess Pda {get; set;}
}

var productBusiness = new ProductBusiness();
productBusiness.Pda = new ProductDataAccess();
productBusiness.Pda = new MockProductDataAccess();

Or constructor injection:

public class ProductBusiness
{
    private readonly IProductDataAccess _pda;

    public ProductBusiness(IProductDataAccess pda)
    {

        _pda = pda;
    }
}

var productBusiness = new ProductBusiness(new ProductDataAccess());
var productBusiness = new ProductBusiness(new MockProductDataAccess());

Constructor injection is usually the recommend approach. Property injection is used for optional dependencies (e.g., instantiate a concrete NullLogger by default in the constructor, and use the property to optionally inject a working logger).

Upvotes: 9

Related Questions