linq to entity datediff未通过单元测试,但不是sql数据

问题描述 投票:2回答:2

我有一个LINQ to实体单元测试需要获得员工的timeOut - timeIn他们在一周内工作的每一天并将它们加在一起。在提取sql数据时该方法很好,但在单元测试中我得到错误:“此函数只能从LINQ实体调用。”

这似乎是一件非常简单的事情,但我已经尝试了很多东西,无法通过测试。不想仅仅为测试添加大量代码,因为这会破坏测试的目的(在几年前类似的问题中提到)。我想知道是否有任何更新的方法可以让它工作而不会添加会使方法复杂化的大量代码。

方法:

    #region CalculateTimeToPay(payrollWeekEnd)
    public IQueryable<CalculatedHours> CalculateTimeToPay(DateTime payrollWeekStart, DateTime payrollWeekEnd)
    {
        var uow = container.Resolve<WWIncomeTaxDataHandlerUnitOfWork>();

        var employeeHours = (from time in uow.Accounting.Repository.Find<V_Time>()
                             where (payrollWeekEnd >= time.PayTimeIn && time.PayTimeIn >= payrollWeekStart)
                             group time by new { EmployeeID = time.EmployeeID} into empGroup
                             select new CalculatedHours
                             {
                                 EmployeeID = empGroup.Key.EmployeeID,
                                 //TimeToPay = (empGroup.Sum(x => (SqlFunctions.DateDiff("second", x.PayTimeIn, x.PayTimeOut)) / 60.0 / 60.0)) ?? 0
                                 //TimeToPay = empGroup.Sum(x => x.PayTimeOut - x.PayTimeIn) //empGroup.Sum(x => (SqlFunctions.DateDiff("second", x.PayTimeIn, x.PayTimeOut)) / 60.0 / 60.0) ?? 0

                                 TimeToPay = (empGroup.Where(x => x.EmployeeID == empGroup.Key.EmployeeID).Sum(x => (SqlFunctions.DateDiff("second", x.PayTimeIn, x.PayTimeOut))/60.0/60.0)) ?? 0
                             });

        //var employeeHours = (from time in uow.Accounting.Repository.Find<V_Time>()
        //                     where (payrollWeekEnd >= time.PayTimeIn && time.PayTimeIn >= payrollWeekStart)
        //                     group time by new { time.EmployeeID } into empGroup
        //                     select new CalculatedHours
        //                     {
        //                         EmployeeID = empGroup.Key.EmployeeID,
        //                         //TimeToPay = (empGroup.Sum(x => (SqlFunctions.DateDiff("second", x.PayTimeIn, x.PayTimeOut)) / 60.0 / 60.0)) ?? 0
        //                         TimeToPay = (empGroup.Sum(x => (SqlFunctions.DateDiff("second", x.PayTimeIn, x.PayTimeOut)) / 60.0 / 60.0)) ?? 0

        //                         //TimeToPay = (empGroup.Where(x => x.EmployeeID == empGroup.Key.EmployeeID).Sum(x => (SqlFunctions.DateDiff("second", x.PayTimeIn, x.PayTimeOut))/60.0/60.0)) ?? 0
        //                     }); 

        return employeeHours;
    }
    #endregion

测试:

    #region CalculateTimeToPay_IntegerEmployeeIDAndDateTimeWeekOfDate_IQueryableTimeToPay
    [TestMethod]
    public void CalculateTimeToPay_IntegerEmployeeIDAndDateTimeWeekOfDate_IQueryableTimeToPay()
    {
        //Arrange
        var service = new WWIncomeTaxDataHandlerService("ProdSQL");
        DateTime payrollWeekEnd = Convert.ToDateTime("2017-01-15");
        DateTime payrollWeekStart = Convert.ToDateTime("2017-01-09");

        var V_Times = new List<V_Time>()
        {
            new V_Time { PayTimeIn = Convert.ToDateTime("2017-01-05 08:00:00.000"), PayTimeOut = Convert.ToDateTime("2017-01-05 16:00:00.000"), EmployeeID = 999 },
            new V_Time { PayTimeIn = Convert.ToDateTime("2017-01-05 08:30:00.000"), PayTimeOut = Convert.ToDateTime("2017-01-05 16:00:00.000"), EmployeeID = 777 },
            new V_Time { PayTimeIn = Convert.ToDateTime("2017-01-05 08:45:00.000"), PayTimeOut = Convert.ToDateTime("2017-01-05 16:00:00.000"), EmployeeID = 888 },
            new V_Time { PayTimeIn = Convert.ToDateTime("2017-01-10 08:00:00.000"), PayTimeOut = Convert.ToDateTime("2017-01-10 16:00:00.000"), EmployeeID = 999 },
            new V_Time { PayTimeIn = Convert.ToDateTime("2017-01-10 08:30:00.000"), PayTimeOut = Convert.ToDateTime("2017-01-10 16:00:00.000"), EmployeeID = 777 },
            new V_Time { PayTimeIn = Convert.ToDateTime("2017-01-10 08:45:00.000"), PayTimeOut = Convert.ToDateTime("2017-01-10 16:00:00.000"), EmployeeID = 888 },
            new V_Time { PayTimeIn = Convert.ToDateTime("2017-01-11 08:00:00.000"), PayTimeOut = Convert.ToDateTime("2017-01-11 16:00:00.000"), EmployeeID = 999 },
            new V_Time { PayTimeIn = Convert.ToDateTime("2017-01-11 00:00:00.000"), PayTimeOut = Convert.ToDateTime("2017-01-11 07:00:00.000"), EmployeeID = 777 },
            new V_Time { PayTimeIn = Convert.ToDateTime("2017-01-11 08:00:00.000"), PayTimeOut = Convert.ToDateTime("2017-01-11 16:00:00.000"), EmployeeID = 888 },
            new V_Time { PayTimeIn = Convert.ToDateTime("2017-01-12 08:00:00.000"), PayTimeOut = Convert.ToDateTime("2017-01-12 16:00:00.000"), EmployeeID = 999 },
            new V_Time { PayTimeIn = Convert.ToDateTime("2017-01-12 08:00:00.000"), PayTimeOut = Convert.ToDateTime("2017-01-12 16:44:00.000"), EmployeeID = 777 },
            new V_Time { PayTimeIn = Convert.ToDateTime("2017-01-12 08:00:00.000"), PayTimeOut = Convert.ToDateTime("2017-01-12 16:00:00.000"), EmployeeID = 888 },
            new V_Time { PayTimeIn = Convert.ToDateTime("2017-01-14 08:00:00.000"), PayTimeOut = Convert.ToDateTime("2017-01-14 16:07:00.000"), EmployeeID = 777 }
        };

        var mockRepository = new Mock<IRepository>();
        mockRepository.Setup(x => x.Find<V_Time>()).Returns(V_Times.AsQueryable());
        var builder = BuildContainer();
        builder.Register(x => mockRepository.Object).As<IRepository>();
        var container = builder.Build();

        var itrs = container.Resolve<WWIncomeTaxDataHandler.Domain.WWIncomeTaxDataHandlerService>();

        var expected = new List<CalculatedHours>()
        {
            new CalculatedHours { EmployeeID = 999, TimeToPay = 24 },
            new CalculatedHours { EmployeeID = 777, TimeToPay = 31.35},
            new CalculatedHours { EmployeeID = 888, TimeToPay = 23.25}
        };

        //Act
        var actual = itrs.CalculateTimeToPay(payrollWeekStart, payrollWeekEnd).ToList();

        //Assert
        var compareLogic = new CompareLogic();
        var result = compareLogic.Compare(actual, expected);
        Assert.IsTrue(result.AreEqual, result.DifferencesString);
    }
    #endregion
c# entity-framework linq unit-testing
2个回答
1
投票

在内存收集使用这样的日期不同的秒

var diffInSeconds = (dateTime1 - dateTime2).TotalSeconds;

您正在使用的功能是使用sql数据库而不是内存集合。


它的失败是因为你依赖floatdecimal的值,我建议你尝试像Math.Round(val,2)和检查结果然而比较两个小数或浮点数总是问题,更好的放置值将给你整数值而没有小数部分。

下面是双重比较的一个例子,这导致输出值qazxsw poi在你的情况下发生同样的事情。

false

你可以在这里查看:// Initialize two doubles with apparently identical values double double1 = .33333; double double2 = 1/3; // Compare them for equality Console.WriteLine(double1.Equals(double2)); // displays false

我在谈论你的代码的这一部分

Double.Equals Method (Double)

1
投票

你已经提到LINQ to entities;因此,我建议你在测试和代码中尝试使用TimeToPay = (empGroup.Where(x => x.EmployeeID == empGroup.Key.EmployeeID).Sum(x => (SqlFunctions.DateDiff("second", x.PayTimeIn, x.PayTimeOut))/60.0/60.0)) ?? 0 (我之前遇到过这个问题并且这个问题发生了变化。这是一个相关的问题,导致其他相关问题:Dbfunctions

但是,SqlFunctions vs DbFunctions没有DbFunctions,所以你必须在你的情况下使用DateDiff

因此,您的行将更改为:

DiffSeconds

注意:这仅适用于查询提供程序被充分模拟的测试。可以使用TimeToPay = (empGroup.Where(x => x.EmployeeID == empGroup.Key.EmployeeID).Sum(x => (DbFunctions.DiffSeconds(x.PayTimeIn, x.PayTimeOut))/60.0/60.0)) ?? 0 Effort.EF6如何插入)或EF Core的内存数据库。您可以尝试模拟自己的提供程序,但这只是让这些测试工作的一个可怕的想法。

此外,一旦您切换到适当的内存数据上下文,而不是模拟here's a post方法,您将列表保存到数据库,然后像往常一样查询它。

© www.soinside.com 2019 - 2024. All rights reserved.