我正在尝试测试查询是否区分大小写。此生产代码有效:
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()
。生产代码正确地忽略了这一点。测试代码没有。
答案 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);
}
}