In the domain-driven model, dependency injection is often used, most of which are implemented through interfaces. A typical application in ASP. NET mvc3 is to call the actual repository code through the irepository interface in the driver model. In the TDD development process, we often haven't implemented the repository code. To test the correctness of the domain-Driven Model Rules (rule), the clumsy method is to make a hypothetical repository implementation, now you can use the Moq plug-in to quickly implement repository.
The procedure is as follows:
1. If you want to operate the product, define the model:
Public class product
{
Public int productid {Get; set ;}
Public string name {Get; set ;}
Public String description {Get; set ;}
Public decimal price {Get; set ;}
Public String category {Get; set ;}
}
2. Define the repository and introduce interface decoupling.
Public interface iproductrepository
{
Ienumerable <product> getproducts ();
Void updateproduct (product P );
}
Note: Virtual implementation (clumsy)
Public class fakerepository: iproductrepository
{
Product [] prods = {
New product {name = "A", price = 50 m },
New product {name = "B", price = 60 m },
New product {name = "C", price = 70 m}
};
Public ienumerable <product> getproducts ()
{
// Mock. Setup (E => E. getproducts (). Returns (prods );
Return prods;
}
Public int updatedproductcount {Get; set ;}
Public void updateproduct (product P)
{
Foreach (product pro in prods. Where (E => E. Name = P. Name). Select (E => E ))
{
Pro. Price = P. price;
}
Updatedproductcount ++;
}
Public decimal gettotalvalue ()
{
Return prods. sum (E => E. Price );
}
}
3. Define domain model rules and operations
Public interface ipricereducer
{
Void pricereduce (decimal price );
}
Public class mypricereducer: ipricereducer
{
Private iproductrepository IPR;
Public mypricereducer (iproductrepository IPR)
{
This. IPR = IPR;
}
Public void pricereduce (decimal price)
{
Foreach (product P in IPR. getproducts ())
{
P. Price = math. Max (P. Price-price, 1 );
IPR. updateproduct (P );
}
}
}
Test code:
[Testmethod]
Public void allpricesarechanged ){
// Arrange
Fakerepository repo = new fakerepository ();
Decimal reduamoamount = 10;
Ienumerable <decimal> prices = Repo. getproducts (). Select (E => E. Price );
Decimal [] initialprices = prices. toarray ();
Mypricereducer target = new mypricereducer (repo );
// Act
Target. performanceprices (reduamoamount );
Prices. Zip (initialprices, (P1, P2) => {
If (p1 = P2 ){
Assert. Fail ();
}
Return P1;
});
}
Use Moq for piling testing:
First, add Moq. dll (in the test project ),
Then, because there is no fakerepository implementation, you need to prepare the data:
[Testinitialize ()]
Public void mytestinitialize ()
{
Prods = new [] {
New product {name = "A", price = 50 m },
New product {name = "B", price = 60 m },
New product {name = "C", price = 70 m}
};
}
It is best to write in the test method as follows:
[Testmethod ()]
Public void allpricearechanged ()
{
Mock <iproductrepository> mipr = new mock <iproductrepository> ();
Mipr. Setup (E => E. getproducts (). Returns (prods );
Mypricereducer target = new mypricereducer (mipr. Object); // todo: Initialize to an appropriate value.
Decimal price = 10 m; // todo: Initialize to an appropriate value.
// Decimal initialtotal = prods. sum (E => E. Price );
Target. pricereduce (price );
Foreach (product P in prods)
{
Mipr. Verify (M => M. updateproduct (P), times. Once ());
}
}
Note:
1. Add using Moq;
2. Mock <> Simulation
3. Setup (unimplemented interface method). Returns (assuming the data returned by the method) implements the core idea of directly specifying the returned data without implementing the method body.
4. Reference mock. object in the domain model to call the specific implementation.