[英]How to unit test method that uses DbContext.Database.SqlQuery<T>
I have written a method that gets data from the database using DbContext.Database.SqlQuery() (EF6.1): 我编写了一种使用DbContext.Database.SqlQuery()(EF6.1)从数据库获取数据的方法:
internal List<WorkOrderLine> Get()
{
var sql = GetSql();
var workOrders = Context.Database.SqlQuery<Model.Analysis.WorkOrder>(sql).ToList();
return workOrders.Select(workOrder => new WorkOrderLine
{
Id = workOrder.a,
Title = workOrder.b,
Status = workOrder.c,
Location = workOrder.d,
AssignedTo = workOrder.e,
StartDate = workOrder.f,
DueDate = workOrder.g,
CompletedDate = h
}).ToList();
}
I want to write a unit test for the method and check that the expected SQL is passed into SQLQuery and then to pass back a list of data so that it can be processed via the rest of the method so that I can check the output. 我想为该方法编写一个单元测试,并检查预期的SQL是否传递到SQLQuery中,然后传递回一个数据列表,以便可以通过该方法的其余部分进行处理,以便可以检查输出。
I believe the correct/best approach would be to mock the DbContext and pass this mocked context into the class instead of a real context. 我相信正确/最好的方法将是模拟DbContext并将此模拟的上下文传递给类而不是真实的上下文。 If so, I think I might be able to do this with one of the following: 如果是这样,我想我可以通过以下其中一种方法来做到这一点:
Use Moq 使用起订量
Manually create a mock to carry out the tests and return the data 手动创建模拟以执行测试并返回数据
Is using mocks the correct technique? 使用模拟是正确的技术吗?
If so, which of these 2 options is the simplest/best? 如果是这样,这两个选项中哪个最简单/最好?
PS I usually use Effort when testing with EF but it doesn't handle this method. PS:在使用EF进行测试时,我通常会使用Effort,但它无法处理这种方法。
EDIT: 编辑:
Here is the complete class: 这是完整的类:
internal Report(MyContext context, ChartWidgetFilter filters, string ownerEntityFilter)
: base(context, filters, ownerEntityFilter)
{
}
internal List<WorkOrderLine> Get()
{
var sql = GetSql();
var workOrders = Context.Database.SqlQuery<Model.Analysis.WorkOrder>(sql).ToList();
return workOrders.Select(workOrder => new WorkOrderLine
{
Id = workOrder.a,
Title = workOrder.b,
Status = workOrder.c,
Location = workOrder.d,
AssignedTo = workOrder.e,
StartDate = workOrder.f,
DueDate = workOrder.g,
CompletedDate = h
}).ToList();
}
private string GetSql()
{
//return the sql generated using the filters and ownerEntityFilter
//parameters passed into the constructor
}
}
EDIT 2: 编辑2:
The two things that I need to test are that: 我需要测试的两件事是:
GetSql() creates the correct SQL for the parameters passed into the constructor - ChartWidgetFilter filters, string ownerEntityFilter
GetSql()为传递到构造函数中的参数创建正确的SQL- ChartWidgetFilter filters, string ownerEntityFilter
That the return workOrders.Select...
statement returns a correctly mapped list of WorkOrderLine
objects for a list of Model.Analysis.WorkOrder
objects 那return workOrders.Select...
语句返回的正确映射列表WorkOrderLine
对象的列表Model.Analysis.WorkOrder
对象
Here is a example about how to "mock" for a unit test 这是有关如何“模拟”单元测试的示例
public class SolvencyBllTest
{
private MyAttBLL myAttBll;
private readonly List<AttestationEntity> attestationsFakeForTest = new List<AttestationEntity>
{
/// ... Build the child object , used for 'mock'
}
//Initialize event => here we define what the 'mock' should to de when we use the [GetListWithChildren] function
[TestInitialize]
public void Setup()
{
var mockedAttestationFakeToTest = new Mock<IAttestationDataAccessLayer>();
//setup GetAll : return the whole list
mockedAttestationFakeToTest
.Setup(attestation => attestation.GetListWithChildren(It.IsAny<Expression<Func<AttestationEntity, bool>>>()))
.Returns((Expression<Func<AttestationEntity, bool>> expression) =>
{
return this.attestationsFakeForTest.AsQueryable().Where(expression);
});
this.myAttBll = new MyAttBLL(attestationsCertificatesRefundDal: null, attestationDal: mockedAttestationFakeToTest.Object, emailNotifier: mockedEmailNotifier.Object);
}
[TestMethod]
public void SolvencyBllTest_CheckAttestation()
{
// Initalize the result
SolvencyCheckResult solvencyCheckResult = new SolvencyCheckResult()
{
solvency = new SolvencyModel()
};
// Declare and initializes our object which encapsulates our parameters for the solvency check
SolvencyCheckParameters solvencyCheckParams = new SolvencyCheckParameters(TestConstants.Contact.LAST_NAME, TestConstants.Contact.FIRST_NAME, TestConstants.Contact.BIRTH_DATE, TestConstants.Address.STREET, TestConstants.Address.ZIPCODE, TestConstants.UNIT_TEST_USER);
// this (solvencyBll) will not try to find in the database but in the collection with just mock before
// Try to retrieve all certificates dating back 3 months and have the same name + first name + date of birth
List<AttestationModel> attsLatestToCheck = this.myAttBll.CheckLatestAttestation(solvencyCheckResult, solvencyCheckParams);
// 1 attestation created today => OK
// 1 attestation created 1 month ago => OK
// 1 attestation created 2 month ago => OK
// 1 attestation created 4 month ago => KO
Assert.AreEqual(3, attsLatestToCheck.Count);
}
Example for use the dbContext from the BLL part functions 在BLL零件函数中使用dbContext的示例
public IEnumerable<AttestationEntity> GetListWithChildren(Expression<Func<AttestationEntity, bool>> pred)
{
using (ScDbContext context = new ScDbContext())
{
return this.GetListWithChildrenInternal(context, pred).OrderBy(att => att.CreatedDate).ToList();
}
}
internal IEnumerable<AttestationEntity> GetListWithChildrenInternal(ScDbContext context, Expression<Func<AttestationEntity, bool>> pred)
{
return this.GetListInternal(context, pred, attestationChildren).OrderBy(att => att.CreatedDate).ToList();
}
internal IEnumerable<E> GetListInternal(DBC context, Expression<Func<E, bool>> where, params Expression<Func<E, object>>[] navigationProperties)
{
IQueryable<E> dbQuery = context.Set<E>();
//Apply eager loading
foreach (Expression<Func<E, object>> navigationProperty in navigationProperties)
dbQuery = dbQuery.Include<E, object>(navigationProperty);
return dbQuery
//.AsNoTracking() //Don't track any changes for the selected item
.Where(where)
.ToList(); //Apply where clause
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.