C# 如何对使用DbContext.Database.SqlQuery的方法进行单元测试<;T>;
我编写了一个使用DbContext.database.SqlQuery()从数据库获取数据的方法(EF6.1):C# 如何对使用DbContext.Database.SqlQuery的方法进行单元测试<;T>;,c#,entity-framework,unit-testing,C#,Entity Framework,Unit Testing,我编写了一个使用DbContext.database.SqlQuery()从数据库获取数据的方法(EF6.1): 内部列表Get() { var sql=GetSql(); var workOrders=Context.Database.SqlQuery(sql.ToList(); 返回工单。选择(工单=>新工单行 { Id=工作订单.a, 标题=工作订单.b, 状态=workOrder.c, 位置=workOrder.d, AssignedTo=workOrder.e, StartDate=工
内部列表Get()
{
var sql=GetSql();
var workOrders=Context.Database.SqlQuery(sql.ToList();
返回工单。选择(工单=>新工单行
{
Id=工作订单.a,
标题=工作订单.b,
状态=workOrder.c,
位置=workOrder.d,
AssignedTo=workOrder.e,
StartDate=工作顺序.f,
DueDate=workOrder.g,
完成日期=小时
}).ToList();
}
我想为该方法编写一个单元测试,检查预期的SQL是否传递到SQLQuery中,然后传回一个数据列表,以便可以通过该方法的其余部分对其进行处理,以便检查输出
我认为正确/最好的方法是模拟DbContext,并将模拟的上下文传递到类中,而不是真正的上下文。如果是这样的话,我想我可以通过以下方法之一做到这一点:
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
}
}
内部报告(MyContext上下文、ChartWidgetFilter筛选器、string ownerEntityFilter)
:base(上下文、筛选器、ownerEntityFilter)
{
}
内部列表Get()
{
var sql=GetSql();
var workOrders=Context.Database.SqlQuery(sql.ToList();
返回工单。选择(工单=>新工单行
{
Id=工作订单.a,
标题=工作订单.b,
状态=workOrder.c,
位置=workOrder.d,
AssignedTo=workOrder.e,
StartDate=工作顺序.f,
DueDate=workOrder.g,
完成日期=小时
}).ToList();
}
私有字符串GetSql()
{
//返回使用筛选器和ownerEntityFilter生成的sql
//传递到构造函数中的参数
}
}
编辑2:
我需要测试的两件事是:
ChartWidgetFilter过滤器,string ownerEntityFilter
return workOrders.Select…
语句为Model.Analysis.WorkOrder
对象列表返回正确映射的WorkOrderLine
对象列表下面是一个关于如何“模拟”单元测试的示例
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);
}
公共类SolvencyBllTest
{
私人MyAttBLL MyAttBLL;
私有只读列表认证Makefortest=新列表
{
///…生成用于“mock”的子对象
}
//Initialize event=>在这里,我们定义了在使用[GetListWithChildren]函数时“mock”应该定义的内容
[测试初始化]
公共作废设置()
{
var mockedAttestationFakeToTest=new Mock();
//setup GetAll:返回整个列表
模拟试验
.Setup(detection=>detection.GetListWithChildren(It.IsAny()))
.Returns((表达式)=>
{
返回此.detectionsFakeforTest.AsQueryable().Where(表达式);
});
this.myAttBll=新的myAttBll(DetectionsCertificatesRefundDal:null,DetectionDal:MockedAttestStationFaketotest.Object,emailNotifier:mockedEmailNotifier.Object);
}
[测试方法]
公共无效SolvencyBllTest_CheckDetection()
{
//初始化结果
SolvencyCheckResult SolvencyCheckResult=新的SolvencyCheckResult()
{
偿付能力=新的偿付能力模型()
};
//声明并初始化封装偿付能力检查参数的对象
SolvencyCheckParameters SolvencyCheckParamers=新的SolvencyCheckParameters(TestConstants.Contact.LAST_名称、TestConstants.Contact.FIRST_名称、TestConstants.Contact.BIRTH_日期、TestConstants.Address.STREET、TestConstants.Address.ZIPCODE、TestConstants.UNIT_测试用户);
//此(solvencyBll)将不会尝试在数据库中查找,而是在之前使用mock的集合中查找
//尝试检索3个月前的所有证书,并且具有相同的姓名+名字+出生日期
List attsLatestToCheck=this.myAttBll.checklateStateTStateTStation(solvencyCheckResult,solvencyCheckParams);
//1今天创建的认证=>OK
//1个月前创建的认证=>OK
//1个月前创建的认证=>正常
//1 4个月前创建的认证=>KO
AreEqual(3,attsLatestToCheck.Count);
}
使用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
}
public IEnumerable GetListWithChildren(表达式pred)
{
使用(ScDbContext上下文=新的ScDbContext())
{
返回此.GetListWithChildrenInternal(context,pred).OrderBy(att=>att.CreatedDate).ToList();
}
}
内部IEnumerable GetListWithChildrenInternal(ScDbContext上下文,表达式pred)
{
返回这个.GetListInternal(context,pred,detectionChildren).OrderBy(att=>att.CreatedDate).ToList();
}
内部IEnumerable GetListInternal(DBC上下文、表达式where、参数表达式[]navigationProperties)
{
IQueryable dbQuery=context.Set();
//应用即时加载
foreach(navigationProperties中的表达式navigationProperty)
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
}