试图模拟可查询实体框架查询

时间:2018-10-11 18:04:56

标签: c# entity-framework linq iqueryable

我正在尝试测试查询是否区分大小写。此生产代码有效:

public ILookup<string, EEntry> GetEEntries(int batchId, List<string> employeeIds)
{
  using (WithNoLock())
  {
    var result = from e in _entities.EEntries
                 where e.CPayBatchProcessId == batchId
                       && (!e.Blocked.HasValue || e.Blocked.Value != true)
                       && employeeIds.Contains(e.Id)
                 select e;

    return result.ToLookup(e => e.Id, StringComparer.OrdinalIgnoreCase);
  }
}

我无法进行单元测试。我的第一次尝试失败了,因为我认为列表是IEnumerable而不是IQueryable。但是,我对IQueryable的尝试没有通过。该查询区分大小写,我不希望这样。这就是我所做的IQueryable

[TestCase("abc", "ABC")]
public void EEntriesAreCaseInsensitive(string employeeId1Input, string employeeId1Output)
{
  var payEntries = new List<EEntry>
  {
    new EEntry() {CPayBatchProcessId = 8, Id = employeeId1Input},
    new EEntry() {CPayBatchProcessId = 8, Id = "123"}
  }.AsQueryable();

  var payEntriesDbSet = new Mock<DbSet<EEntry>>();
  payEntriesDbSet.As<IQueryable<EEntry>>().Setup(x => x.Provider).Returns(payEntries.Provider);
  payEntriesDbSet.As<IQueryable<EEntry>>().Setup(x => x.Expression).Returns(payEntries.Expression);
  payEntriesDbSet.As<IQueryable<EEntry>>().Setup(x => x.ElementType).Returns(payEntries.ElementType);
  payEntriesDbSet.As<IQueryable<EEntry>>().Setup(x => x.GetEnumerator()).Returns(payEntries.GetEnumerator);

  var context = new Mock<ISomeContext>();
  context.Setup(x => x.EEntries).Returns(payEntriesDbSet.Object);

  var employeeIds = new List<string>() { "aBc", "dEf", "gHi" };

  var repo = new EEntriesRepository(context.Object);
  var payEntryRecords = repo.GetEEntries(8, employeeIds);

  Assert.IsTrue(payEntryRecords.Contains(employeeId1Output));
}

我想念什么?

注意:EEntry.Id的吸气剂返回.ToUpper()。生产代码正确地忽略了这一点。测试代码没有。

2 个答案:

答案 0 :(得分:0)

看起来您在任何地方都没有使用employeeId1Output,但是您断言它应该位于payEntryRecords中。根据您的代码,您似乎应该断言employeeId1Input中是否包含payEntryRecords。您将employeeId1Input明确添加到payEntries对象中。

答案 1 :(得分:0)

字符串比较的不区分大小写的性质取决于您的数据库提供程序。 SQL Server将比较不区分大小写的字符串,而我相信像PostgreSQL这样的字符串不会区分大小写。

因此,如果您的代码逻辑执行employeeIds.Contains(e.Id),则EF会将等效逻辑传递给数据库。当用Mock和List<T>.AsQueryable()替换它时,C#将把字符串区分大小写,而SQL Server不在乎。 IN()子句和字符串比较不区分大小写。

我会考虑使用以下内容或类似内容来确保字符串比较不区分大小写。这应该可以跨数据库提供程序使用,并且可以更好地放置模拟数据。

public ILookup<string, EEntry> GetEEntries(int batchId, List<string> employeeIds)
{
  if(employeeIds == null) throw new ArgumentNullException("employeeIds");

  employeeIds = employeeIds.ConvertAll(x => x.ToUpper());
  using (WithNoLock())
  {
    var result = from e in _entities.EEntries
                 where e.CPayBatchProcessId == batchId
                       && (!e.Blocked.HasValue || e.Blocked.Value != true)
                       && employeeIds.Contains(e.Id.ToUpper())
                 select e;

    return result.ToLookup(e => e.Id, StringComparer.OrdinalIgnoreCase);
  }
}