Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何对使用DbContext.Database.SqlQuery的方法进行单元测试<;T>;_C#_Entity Framework_Unit Testing - Fatal编程技术网

C# 如何对使用DbContext.Database.SqlQuery的方法进行单元测试<;T>;

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=工

我编写了一个使用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=工作顺序.f,
DueDate=workOrder.g,
完成日期=小时
}).ToList();
}
我想为该方法编写一个单元测试,检查预期的SQL是否传递到SQLQuery中,然后传回一个数据列表,以便可以通过该方法的其余部分对其进行处理,以便检查输出

我认为正确/最好的方法是模拟DbContext,并将模拟的上下文传递到类中,而不是真正的上下文。如果是这样的话,我想我可以通过以下方法之一做到这一点:

  • 使用最小起订量

  • 手动创建模拟以执行测试并返回数据

  • 使用模拟是正确的技术吗

    如果是,这两个选项中哪一个最简单/最好

    另外,我通常在使用EF进行测试时使用努力,但它不能处理这种方法

    编辑:

    以下是完整的课程:

    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:

    我需要测试的两件事是:

  • GetSql()为传递到构造函数的参数创建正确的SQL-
    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
            }