AnandhaSundari M AnandhaSundari M - 2 months ago 7
C# Question

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?

Answer

Classic example which shows how if you cannot unit test a particular component, REFACTOR the component!

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

In your example, the ProductBusiness class is very tightly coupled with the ProductDataAccess. 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 than 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, though 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 we 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, have the ProductBusiness which looks like:

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
Comments