简体   繁体   English

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

[英]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: 如果是这样,我想我可以通过以下其中一种方法来做到这一点:

  1. Use Moq 使用起订量

  2. 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: 我需要测试的两件事是:

  1. GetSql() creates the correct SQL for the parameters passed into the constructor - ChartWidgetFilter filters, string ownerEntityFilter GetSql()为传递到构造函数中的参数创建正确的SQL- ChartWidgetFilter filters, string ownerEntityFilter

  2. 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.

相关问题 DbContext.Database.SqlQuery <T> 使用INNER JOIN不会设置基类属性值 - DbContext.Database.SqlQuery<T> with INNER JOIN doesn't set base class property values 如何将CancellationTokenSource与DbContext.Database.SqlQuery一起使用 <TElement> (Sp,Param)? - How Do I Use CancellationTokenSource With DbContext.Database.SqlQuery<TElement>(Sp, Param)? 如何使用 DbContext.Database.SqlQuery<TElement> (sql, params) 与存储过程? EF Code First CTP5 - How to use DbContext.Database.SqlQuery<TElement>(sql, params) with stored procedure? EF Code First CTP5 如何在不使用参数的情况下使用DbContext.Database.SqlQuery(sql,params)并等待数据结果 - how to use DbContext.Database.SqlQuery(sql, params) without parameters and waiting for a data result C#如何将DbContext.Database.SqlQuery与抽象/派生类一起使用 - C# How to use DbContext.Database.SqlQuery with abstract/derived classes DbContext.Database.SqlQuery不会填充实体框架的额外属性 - Entity Framework extra properties are not populated by DbContext.Database.SqlQuery 必须使用dbcontext.Database.SqlQuery声明标量变量&#39;@custid&#39;? - must declare the scalar variable '@custid' using dbcontext.Database.SqlQuery? DbContext.Database.SqlQuery与ObjectContext.ExecuteFunction - DbContext.Database.SqlQuery vs ObjectContext.ExecuteFunction DbContext.Database.SqlQuery返回一些空对象 - DbContext.Database.SqlQuery returns some null objects 我可以在实体框架 6 中使用没有强元素类型的 DbContext.Database.SqlQuery 吗? - Can I use DbContext.Database.SqlQuery without a strong element type in Entity Framework 6?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM