以下方法与 SQL Server 完美配合,没有问题。
public async Task<IEnumerable<HashRecord>> GetLatestHashes(long jobId, CancellationToken token)
{
var context = _contextFactory.Create();
var hashes = await context.Set<PRH>()
.AsNoTracking()
.Where(x => x.JobId == jobId)
.GroupBy(x => x.Hash)
.Select(g => new HashRecord
{
Hash = g.Key,
Status = g.Any(x => x.Status == RPStatus.Successful) ? RPStatus.Successful :
g.Any(x => x.Status == RPStatus.Failed) ? RPStatus.Failed : RPStatus.Skipped
})
.ToArrayAsync(token);
return hashes;
}
PRH 课程是这样的:
public class PRH
{
public long JobId { get; set; }
public RPStatus Status { get; set; }
public byte[] Hash { get; set; } = Array.Empty<byte>();
}
对于此方法,我必须使用内存数据库创建一个单元测试,但是,由于 GroupBy 正在使用作为字节数组的属性哈希,因此具有相同值的两个数组对于 GroupBy 来说是不同的,因为它是通过引用进行比较.
您建议使用哪些替代方案来应对 GroupBy 的此问题?
考虑向上移动单元测试的边界。这个方法:
// Note: "Async" suffix is highly recommended for async methods.
// It makes spotting and avoiding issues like missed awaits easier.
public async Task<IEnumerable<HashRecord>> GetLatestHashesAsync(long jobId, CancellationToken token)
...基本上是通过 EF 包装数据访问选择,类似于存储库实现。使用这样的存储库包装器的原因之一是为了促进单元测试。因此,请按照以下方式模拟此服务/存储库:
mockHashRepository.Setup(x => x.GetLatestHashesAsync(jobId, It.IsAny<CancellationToken>())
.Returns(Task.FromResult(mockedResults));`
我们不需要对 EF 的 Linq 功能是否正常工作进行单元测试,因为它已经过测试和审查。 如果您想断言 Linq 表达式实际上在给定特定数据状态的情况下返回正确的结果,则应通过针对使用已知数据状态设置的真实数据源进行集成测试来完成,并且该数据源应使用准确的结果您将在生产中使用的数据库提供程序相同。正如您所看到的,内存中数据提供程序具有局限性,即使使用支持分组的数据提供程序,也可能会由于行为差异而导致其他问题出现。 (即不同的排序规则等)针对真实数据库的测试将需要更长的时间来设置、运行和拆除,因此这些测试作为集成测试而不是单元测试运行的频率较低。