I am attempting to mock multiple DbSets and their DbContext. I'm stumped about this one. I appreciate any feedback.
When I run the test, I receive the following null reference exception:
System.NullReferenceException : Object reference not set to an instance of an object.
The exception is thrown here in the test method:
return enterprisePubContext.WrWaterUsage
.Include(wu => wu.WaterUseCodeDescription)
.Include(wu => wu.PhysicalRight)
.ThenInclude(p => p.WaterRight)
.FirstOrDefault(wu => wu.PlaceOfUseId == placeOfUseId && wu.PhysicalRight.WaterRight != null);
However, it does not seem as if the problem is with the query which returns a result from the test method. The problem appears to occur during setup for each mock DbSet, and since setup for mock DbSets fails, then set up for the mock DbContext subsequently fails, and it seems as if a null context is passed to the test method. I have used moq for DbSets before and never encountered this problem.
When I debug the test, I see the following exception for each DbSet and for each Mock<IQueryable<entity>>.Setup<IQueryProvider>
(for example, mockPhysicalRights.As<IQueryable<WrPhysicalRight>>().Setup(m => m.Provider).Returns(physicalRights.Provider)
):
'((Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure)((Moq.Mock)(mockPhysicalRights)).Object).Instance' threw an exception of type 'System.NotImplementedException' '((System.Linq.IQueryable)((Moq.Mock)('mockDbSet')).Object).Provider' threw an exception of type 'System.NotImplementedException' '((Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure)((Moq.Mock)(mockPhysicalRights)).Object).Instance' threw an exception of type 'System.NotImplementedException' '((System.Linq.IQueryable)((Moq.Mock)(mockDbSet)).Object).Expression' threw an exception of type 'System.NotImplementedException' '((Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure)((Moq.Mock)(mockPhysicalRights)).Object).Instance' threw an exception of type 'System.NotImplementedException' '((System.Linq.IQueryable)((Moq.Mock)(mockDbSet)).Object).ElementType' threw an exception of type 'System.NotImplementedException'
Here are screenshot examples of the exceptions in debug mode:
The same exception thrown on mockPhysicalRights.As<IQueryable<WrPhysicalRight>>().Setup(m => m.Provider).Returns(physicalRights.Provider)
is also thrown on:
mockPhysicalRights.As<IQueryable<WrPhysicalRight>>()
.Setup(m => m.Expression).Returns(physicalRights.Expression);
'((System.Linq.IQueryable)((Moq.Mock)(mockPhysicalRights)).Object).Expression' threw an exception of type 'System.NotImplementedException'
mockPhysicalRights.As<IQueryable<WrPhysicalRight>>()
.Setup(m => m.ElementType).Returns(physicalRights.ElementType);
'((System.Linq.IQueryable)((Moq.Mock)(mockPhysicalRights)).Object).ElementType' threw an exception of type 'System.NotImplementedException'
When setting up the DbContext,
var mockEnterprisePubContext = new Mock<EnterprisePubContext>();
mockEnterprisePubContext.Setup(m => m.WrPhysicalRight)
.Returns(mockPhysicalRights.Object);
I see the following error:
error CS0103: The name 'm' does not exist in the current context
Here is a screenshot in debug mode.
Hopefully, I have included all the relevant code below.
DbContext - assumed irrelevant code is omitted for simplicity
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 - assumed irrelevant code is omitted for simplicity
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; }
}
Test methods - assumed irrelevant code is omitted for simplicity
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);
}
}
}
Test
/// <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);
}