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?
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
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);
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 dependency-injection 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 moq. 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 castle-windsor. 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.
链接地址: http://www.djcxy.com/p/54062.html上一篇: 模拟使用Moq的抽象类
下一篇: 嘲笑在C#中使用Moq