EntityFrameworkCore 引发异常,但测试通过

Hui Liu-MSFT 48,531 信誉分 Microsoft 供应商
2024-03-19T07:56:10.3866667+00:00

我使用 Microsoft.EntityFrameworkCore、Microsoft.EntityFrameworkCore.InMemory 和 Microsoft.EntityFrameworkCore.SqlServer 版本 5.0.17

我们在使用上下文数据库内存进行单元测试时遇到了问题,因为某些查询的执行(具有与实际情况相同的值)通过了测试。但是,当我运行一个用例时,该用例与具有相同值的测试达到相同的点,查询会引发异常。

我知道异常的解决方案,但问题是,为什么当我运行使用相同输入参数访问相同查询的测试时不引发异常?

例:

public Hotel GetHotel(int codHotel)
{
	var query = _context
		.Hotel
		.Where(c => c.CodHotel == codHotel)
		.Select(s => new Hotel()
		{
			HotelCode = codHotel,
			TaxInclude = GetTaxType(s.Impuestos) //Exception in real case, not exception in tests
		})
		.FirstOrDefault();
	return query;
}

public static string GetTaxType(decimal? taxType)
{
    return taxType.HasValue ? Common.Constants.INCLUDEDTAXES : Common.Constants.EXCLUDEDTAXES;
}

例外:

客户端投影包含通过实例方法“GetTaxType”对“Barcelo.Integrator.Booking.Repository.HotelRepository”常量表达式的引用。

这可能会导致内存泄漏;请考虑将该方法设为静态,以便它不会在实例中捕获常量。

我知道将此函数更改为静态并解决异常。

但是,真正的问题是......为什么测试不抛出这些异常?

其他示例:

public List<Cancelation> GetAgreements(int hotelCode, string checkIn, string checkOut)
{
	var query = _context
	.AcuerdosTarifaTramos
	.Where(c => c.CodHotel == hotelCode
		&& c.FechaHasta.ToDate(Common.Constants.FORMATDATETIME_YYYYMMDD) >= checkOut.ToDate(Common.Constants.FORMATDATETIME_YYYYMMDD))
	.Select(s => new CancelationPolicy()
	{
		Release = Release
	})
	.ToList();
	return query;
}

抛出异常:

ToDate(“yyyyMMdd”) >= __ToDate_3)' 无法翻译。附加信息: 方法“System.Extensions.ToDate”的翻译失败。

方法“System.Extensions.ToDate”的翻译失败。

以可转换的形式重写查询,或者通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用来显式切换到客户端评估。

同样,实际情况会引发异常,但测试使用相同的输入参数通过

执行中的程序集是相同的数据库上下文和 entityFrameworkCore

区别仅在于实际案例使用 Microsoft.EntityFrameworkCore.SqlServer 5.0.17 加载数据库

和使用 Microsoft.EntityFrameworkCore.InMemory 5.0.17 测试加载数据库

sqlserver 是否有可能处理这些异常而 inmemory 不处理?

我怎样才能使测试可靠?

对于目前的问题,测试毫无价值。

Note:此问题总结整理于:EntityFrameworkCore throws exceptions, but tests pass

Entity Framework Core
Entity Framework Core
实体框架数据访问技术的轻量型、可扩展、开源、跨平台版本。
49 个问题
0 个注释 无注释
{count} 票

接受的答案
  1. Jiale Xue - MSFT 45,006 信誉分 Microsoft 供应商
    2024-03-19T09:05:49.4433333+00:00

    首先,我将解释为什么可以通过测试,但使用案例抛出相关异常。

    请阅读 Microsoft Learning EF Core 内存中数据库提供程序,其中提到了以下内容:

    内存中提供程序不是为在测试环境之外使用而设计的,因此不应将其用作测试环境。

    因此,您可能无法在实际情况下使用它。

    现在我将解释为什么会抛出这两个异常。

    例外:

    客户端投影包含通过实例方法“GetTaxType”对“Barcelo.Integrator.Booking.Repository.HotelRepository”常量表达式的引用。

    这可能会导致内存泄漏;请考虑将该方法设为静态,以便它不会在实例中捕获常量。

    根据我的测试,我重现了这个问题。根据我的研究,可能的原因可能是,如果您在 IQueryable 中包含实例方法,它将被缓存,并且即使在处理上下文后也不会释放该方法。如果你想了解更多关于它的信息,你可以参考这个答案

    方法“System.Extensions.ToDate”的翻译失败。

    以可转换的形式重写查询,或者通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用来显式切换到客户端评估。

    EF Core 不知道如何将 ToDate 方法转换为 SQL 命令。在这里,您可以尝试以下代码来替换 ToDate 方法:

    .Where(c => c.CodHotel == hotelCode
                    && DateTime.ParseExact(c.FechaHasta, Common.Constants.FORMATDATETIME_YYYYMMDD, System.Globalization.CultureInfo.InvariantCulture) >= DateTime.ParseExact(checkOut, Common.Constants.FORMATDATETIME_YYYYMMDD, System.Globalization.CultureInfo.InvariantCulture))
                .Select(s => new Cancelation()
                {
                    Release = Release
                })
    

    如果答案是正确的,请点击“接受答案”并点赞。 如果您对此答案还有其他疑问,请点击“评论”。

    注意:如果您想接收相关电子邮件,请按照我们的文档中的步骤启用电子邮件通知 此线程的通知。

    0 个注释 无注释

0 个其他答案

排序依据: 非常有帮助

你的答案

问题作者可以将答案标记为“接受的答案”,这有助于用户了解已解决作者问题的答案。