我正在尝试模拟多个 DbSet 及其 DbContext。我对这个感到难过。我很感激任何反馈。
当我运行测试时,我收到以下空引用异常:
System.NullReferenceException :对象引用未设置为对象的实例。
在测试方法中这里抛出异常:
return enterprisePubContext.WrWaterUsage
.Include(wu => wu.WaterUseCodeDescription)
.Include(wu => wu.PhysicalRight)
.ThenInclude(p => p.WaterRight)
.FirstOrDefault(wu => wu.PlaceOfUseId == placeOfUseId && wu.PhysicalRight.WaterRight != null);
但是,问题似乎并不在于从测试方法返回结果的查询。该问题似乎出现在每个模拟 DbSet 的设置过程中,并且由于模拟 DbSet 的设置失败,因此模拟 DbContext 的设置随后失败,并且似乎将空上下文传递给测试方法。我以前使用过 DbSet 的最小起订量,但从未遇到过这个问题。
当我调试测试时,我看到每个 DbSet 和每个Mock<IQueryable<entity>>.Setup<IQueryProvider>
(例如,mockPhysicalRights.As<IQueryable<WrPhysicalRight>>().Setup(m => m.Provider).Returns(physicalRights.Provider)
)的以下异常:
'((Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure)((Moq.Mock)(mockPhysicalRights)).Object).Instance' 引发了类型为 'System.NotImplementedException' '((System.Linq.IQueryable)((Moq. Mock)(' mockDbSet ')).Object).Provider' 抛出类型为 'System.NotImplementedException' '((Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure)((Moq.Mock)(mockPhysicalRights)).Object).Instance 的异常' 抛出类型为 'System.NotImplementedException' 的异常 '((System.Linq.IQueryable)((Moq.Mock)( mockDbSet)).Object).Expression' 引发类型为 'System.NotImplementedException' 的异常 '((Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure)((Moq.Mock)(mockPhysicalRights)).Object).Instance' 引发类型异常'System.NotImplementedException' '((System.Linq.IQueryable)((Moq.Mock)( mockDbSet )).Object).ElementType' 引发了“System.NotImplementedException”类型的异常
以下是调试模式下异常的屏幕截图示例:
同样抛出的异常mockPhysicalRights.As<IQueryable<WrPhysicalRight>>().Setup(m => m.Provider).Returns(physicalRights.Provider)
也会被抛出:
mockPhysicalRights.As<IQueryable<WrPhysicalRight>>()
.Setup(m => m.Expression).Returns(physicalRights.Expression);
'((System.Linq.IQueryable)((Moq.Mock)(mockPhysicalRights)).Object).Expression' 引发了“System.NotImplementedException”类型的异常
mockPhysicalRights.As<IQueryable<WrPhysicalRight>>()
.Setup(m => m.ElementType).Returns(physicalRights.ElementType);
'((System.Linq.IQueryable)((Moq.Mock)(mockPhysicalRights)).Object).ElementType' 引发了“System.NotImplementedException”类型的异常
设置 DbContext 时,
var mockEnterprisePubContext = new Mock<EnterprisePubContext>();
mockEnterprisePubContext.Setup(m => m.WrPhysicalRight)
.Returns(mockPhysicalRights.Object);
我看到以下错误:
错误 CS0103:当前上下文中不存在名称“m”
这是调试模式下的屏幕截图。
希望我在下面包含了所有相关代码。
DbContext - 为简单起见省略了假定的不相关代码
public class EnterprisePubContext : DbContext
{
public EnterprisePubContext()
{
}
public EnterprisePubContext(DbContextOptions<EnterprisePubContext> options) : base(options)
{
}
public virtual DbSet<WrPhysicalRight> WrPhysicalRight { get; set; }
public virtual DbSet<WrWaterUsage> WrWaterUsage { get; set; }
public virtual DbSet<WrWaterUseCode> WrWaterUseCode { get; set; }
public virtual DbSet<WrWaterRight> WrWaterRight { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<WrPhysicalRight>(entity =>
{
entity.HasKey(e => e.RightId)
.HasName("wrPhysicalRightPK")
.IsClustered(false);
entity.ToTable("wrPhysicalRight", "dbo");
entity.Property(e => e.RightId).HasColumnName("RightID");
entity.HasOne<WrWaterRight>(pr => pr.WaterRight)
.WithOne(wr => wr.PhysicalRight)
.HasForeignKey<WrWaterRight>(wr => wr.RightId);
});
modelBuilder.Entity<WrWaterRight>(entity =>
{
entity.HasKey(e => new { e.BasinNumber, e.SequenceNumber, e.SplitSuffix })
.HasName("wrWaterRightPK")
.IsClustered(false);
entity.ToTable("wrWaterRight", "dbo");
entity.Property(e => e.SplitSuffix)
.HasMaxLength(2)
.IsUnicode(false);
entity.Property(e => e.Basis)
.HasMaxLength(100)
.IsUnicode(false);
entity.Property(e => e.RightId).HasColumnName("RightID");
entity.Property(e => e.Status)
.HasMaxLength(100)
.IsUnicode(false);
});
modelBuilder.Entity<WrWaterUsage>(entity =>
{
entity.HasKey(e => new { e.WaterUseCode, e.RightId })
.HasName("wrWaterUsagePK")
.IsClustered(false);
entity.ToTable("wrWaterUsage", "dbo");
entity.Property(e => e.WaterUseCode)
.HasMaxLength(2)
.IsUnicode(false);
entity.Property(e => e.RightId).HasColumnName("RightID");
entity.Property(e => e.LargePou).HasColumnName("LargePOU");
entity.Property(e => e.PlaceOfUseId).HasColumnName("PlaceOfUseID");
entity.HasOne<WrPhysicalRight>(usage => usage.PhysicalRight)
.WithMany(pr => pr.WaterUsages)
.HasForeignKey(usage => usage.RightId)
.IsRequired();
entity.HasOne<WrWaterUseCode>(usage => usage.WaterUseCodeDescription)
.WithMany(code => code.Usages)
.HasForeignKey(usage => usage.WaterUseCode)
.IsRequired();
});
modelBuilder.Entity<WrWaterUseCode>(entity =>
{
entity.HasKey(e => e.WaterUseCode)
.HasName("wrWaterUseCodePK")
.IsClustered(false);
entity.ToTable("wrWaterUseCode", "dbo");
entity.Property(e => e.WaterUseCode)
.HasMaxLength(2)
.IsUnicode(false)
.ValueGeneratedNever();
entity.Property(e => e.Description)
.HasMaxLength(255)
.IsUnicode(false);
});
}
}
DbSets - 为简单起见,省略了假定的不相关代码
public class WrPhysicalRight
{
[Key]
public int RightId { get; set; }
[ForeignKey("RightId")]
public IList<WrWaterUsage> WaterUsages { get; set; }
public WrWaterRight WaterRight { get; set; }
}
public class WrWaterUsage
{
public string WaterUseCode { get; set; }
public int RightId { get; set; }
public int? PlaceOfUseId { get; set; }
public double? TotalAcres { get; set; }
public double? AcreLimit { get; set; }
public bool LargePou { get; set; }
public WrPhysicalRight PhysicalRight { get; set; }
public WrWaterUseCode WaterUseCodeDescription { get; set; }
}
public class WrWaterUseCode
{
public string WaterUseCode { get; set; }
public string Description { get; set; }
[ForeignKey("WaterUseCode")]
public IList<WrWaterUsage> Usages { get; set; }
}
public class WrWaterRight
{
[Key]
public int BasinNumber { get; set; }
[Key]
public int SequenceNumber { get; set; }
[Key]
public string SplitSuffix { get; set; }
public int? RightId { get; set; }
public string Status { get; set; }
public string Basis { get; set; }
[ForeignKey("RightId")]
public WrPhysicalRight PhysicalRight { get; set; }
}
测试方法 - 为简单起见,省略了假设的不相关代码
public abstract class Process : Enumeration<string>
{
protected readonly List<string> Aliases = new List<string>();
private Process(int value, string displayName, IEnumerable<string> aliases) : base(value,
displayName)
{
Aliases.Add(displayName);
Aliases.AddRange(aliases);
}
public static readonly Process WaterRight = new WaterRightProcess();
public static WrWaterUsage WaterUsageByPlaceOfUseId(EnterprisePubContext enterprisePubContext,
int placeOfUseId, ref Process process)
{
if (process != null)
return process.GetWaterUsageByPlaceOfUseId(enterprisePubContext, placeOfUseId);
return null;
}
private class WaterRightProcess : Process
{
internal WaterRightProcess() : base(0, "WaterRight", new [] { "right" })
{
}
protected override WrWaterUsage GetWaterUsageByPlaceOfUseId(EnterprisePubContext
enterprisePubContext, int placeOfUseId)
{
//Exception thrown here
return enterprisePubContext.WrWaterUsage
.Include(wu => wu.WaterUseCodeDescription)
.Include(wu => wu.PhysicalRight)
.ThenInclude(p => p.WaterRight)
.FirstOrDefault(wu => wu.PlaceOfUseId == placeOfUseId && wu.PhysicalRight.WaterRight
!= null);
}
}
}
测试
/// <summary>
/// Ensure that water right process returns PlaceOfUse by PlaceOfUseId appropriately
/// </summary>
[Fact]
public void WaterRightProcessReturnsWaterUsageByPlaceOfUseWithMocking()
{
//Mocking physical rights entity
var physicalRights = new List<WrPhysicalRight>
{
new WrPhysicalRight
{
RightId = 1
}
}.AsQueryable();
var mockPhysicalRights = new Mock<DbSet<WrPhysicalRight>>();
mockPhysicalRights.As<IQueryable<WrPhysicalRight>>()
.Setup(m => m.Provider).Returns(physicalRights.Provider);
mockPhysicalRights.As<IQueryable<WrPhysicalRight>>()
.Setup(m => m.Expression).Returns(physicalRights.Expression);
mockPhysicalRights.As<IQueryable<WrPhysicalRight>>()
.Setup(m => m.ElementType).Returns(physicalRights.ElementType);
mockPhysicalRights.As<IQueryable<WrPhysicalRight>>()
.Setup(m => m.GetEnumerator()).Returns(physicalRights.GetEnumerator());
//Mocking water usages entity
var waterUsages = new List<WrWaterUsage>
{
new WrWaterUsage
{
RightId = 1,
WaterUseCode = "01",
PlaceOfUseId = 1,
AcreLimit = 12,
TotalAcres = 12,
LargePou = false
}
}.AsQueryable();
var mockWaterUsages = new Mock<DbSet<WrWaterUsage>>();
mockWaterUsages.As<IQueryable<WrWaterUsage>>()
.Setup(m => m.Provider).Returns(waterUsages.Provider);
mockWaterUsages.As<IQueryable<WrWaterUsage>>()
.Setup(m => m.Expression).Returns(waterUsages.Expression);
mockWaterUsages.As<IQueryable<WrWaterUsage>>()
.Setup(m => m.ElementType).Returns(waterUsages.ElementType);
mockWaterUsages.As<IQueryable<WrWaterUsage>>()
.Setup(m => m.GetEnumerator()).Returns(waterUsages.GetEnumerator());
//Mocking water use codes entity
var waterUseCodes = new List<WrWaterUseCode>
{
new WrWaterUseCode
{
WaterUseCode = "01",
Description = "IRRIGATION"
}
}.AsQueryable();
var mockWaterUseCodes = new Mock<DbSet<WrWaterUseCode>>();
mockWaterUseCodes.As<IQueryable<WrWaterUseCode>>()
.Setup(m => m.Provider).Returns(waterUseCodes.Provider);
mockWaterUseCodes.As<IQueryable<WrWaterUseCode>>()
.Setup(m => m.Expression).Returns(waterUseCodes.Expression);
mockWaterUseCodes.As<IQueryable<WrWaterUseCode>>()
.Setup(m => m.ElementType).Returns(waterUseCodes.ElementType);
mockWaterUseCodes.As<IQueryable<WrWaterUseCode>>()
.Setup(m => m.GetEnumerator()).Returns(waterUseCodes.GetEnumerator());
//Mocking water rights entity
var waterRights = new List<WrWaterRight>
{
new WrWaterRight
{
RightId = 1,
BasinNumber = 63
SequenceNumber = 9874,
SplitSuffix = "",
Status = "Active",
Basis = "Statutory Claim"
}
}.AsQueryable();
var mockWaterRights = new Mock<DbSet<WrWaterRight>>();
mockWaterRights.As<IQueryable<WrWaterRight>>()
.Setup(m => m.Provider).Returns(waterRights.Provider);
mockWaterRights.As<IQueryable<WrWaterRight>>()
.Setup(m => m.Expression).Returns(waterRights.Expression);
mockWaterRights.As<IQueryable<WrWaterRight>>()
.Setup(m => m.ElementType).Returns(waterRights.ElementType);
mockWaterRights.As<IQueryable<WrWaterRight>>()
.Setup(m => m.GetEnumerator()).Returns(waterRights.GetEnumerator());
//Mocking EnterprisePubContext
var mockEnterprisePubContext = new Mock<EnterprisePubContext>();
mockEnterprisePubContext.Setup(m => m.WrPhysicalRight)
.Returns(mockPhysicalRights.Object);
mockEnterprisePubContext.Setup(m => m.WrWaterUsage)
.Returns(mockWaterUsages.Object);
mockEnterprisePubContext.Setup(m => m.WrWaterUseCode)
.Returns(mockWaterUseCodes.Object);
mockEnterprisePubContext.Setup(m => m.WrWaterRight)
.Returns(mockWaterRights.Object);
Process process = Process.WaterRight;
var waterUsage = Process.WaterUsageByPlaceOfUseId(mockEnterprisePubContext.Object, 1, ref
process);
Assert.Equal("01", waterUsage.WaterUseCode);
}