Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Moq和Include的单元测试问题(EF6)_C#_Entity Framework_Mocking_Nunit_Moq - Fatal编程技术网

C# Moq和Include的单元测试问题(EF6)

C# Moq和Include的单元测试问题(EF6),c#,entity-framework,mocking,nunit,moq,C#,Entity Framework,Mocking,Nunit,Moq,我已经做了相当多的研究,并尝试了各种不同的方式让考试通过,但现在我需要一些帮助 我正在尝试测试以下存储库方法: 上下文如下所示: public interface IAuthDbContext : IDbContextBase { } public interface IDbContextBase { IDbSet<T> Set<T>() where T : class; IEnumerable<DbValidationError> Get

我已经做了相当多的研究,并尝试了各种不同的方式让考试通过,但现在我需要一些帮助

我正在尝试测试以下存储库方法:

上下文如下所示:

public interface IAuthDbContext : IDbContextBase
{

}

public interface IDbContextBase
{
    IDbSet<T> Set<T>() where T : class;
    IEnumerable<DbValidationError> GetEntityValidationErrors();
    int SaveChanges();
    Task<int> SaveChangesAsync();
    Task<int> SaveChangesAsync(CancellationToken cancellationToken);
}
    protected override void GivenThat()
    {
        var mockRolesSet = GetMockDbSet(PortalRoles().AsQueryable());
        mockRolesSet.Setup(x => x.Include("PortalRole")).Returns(mockRolesSet.Object);

        var mockDomainsSet = GetMockDbSet(PortalDomains().AsQueryable());
        mockDomainsSet.Setup(x => x.Include("PortalDomain")).Returns(mockDomainsSet.Object);

        var mockPortalDomanRolesSet = GetMockDbSet(PortalDomainRoles().AsQueryable());

        mockPortalDomanRolesSet.Setup(x => x.Include("PortalRole")).Returns(mockPortalDomanRolesSet.Object);
        mockPortalDomanRolesSet.Setup(x => x.Include("PortalDomain")).Returns(mockPortalDomanRolesSet.Object);

        var customDbContextMock = new Mock<IAuthDbContext>();
        customDbContextMock.Setup(x => x.Set<PortalRole>()).Returns(mockRolesSet.Object);
        customDbContextMock.Setup(x => x.Set<PortalDomain>()).Returns(mockDomainsSet.Object);
        customDbContextMock.Setup(x => x.Set<PortalDomainRole>()).Returns(mockPortalDomanRolesSet.Object);

        ClassUnderTest = new PortalsRepository(customDbContextMock.Object);
    }
我的单元测试设置如下所示:

public interface IAuthDbContext : IDbContextBase
{

}

public interface IDbContextBase
{
    IDbSet<T> Set<T>() where T : class;
    IEnumerable<DbValidationError> GetEntityValidationErrors();
    int SaveChanges();
    Task<int> SaveChangesAsync();
    Task<int> SaveChangesAsync(CancellationToken cancellationToken);
}
    protected override void GivenThat()
    {
        var mockRolesSet = GetMockDbSet(PortalRoles().AsQueryable());
        mockRolesSet.Setup(x => x.Include("PortalRole")).Returns(mockRolesSet.Object);

        var mockDomainsSet = GetMockDbSet(PortalDomains().AsQueryable());
        mockDomainsSet.Setup(x => x.Include("PortalDomain")).Returns(mockDomainsSet.Object);

        var mockPortalDomanRolesSet = GetMockDbSet(PortalDomainRoles().AsQueryable());

        mockPortalDomanRolesSet.Setup(x => x.Include("PortalRole")).Returns(mockPortalDomanRolesSet.Object);
        mockPortalDomanRolesSet.Setup(x => x.Include("PortalDomain")).Returns(mockPortalDomanRolesSet.Object);

        var customDbContextMock = new Mock<IAuthDbContext>();
        customDbContextMock.Setup(x => x.Set<PortalRole>()).Returns(mockRolesSet.Object);
        customDbContextMock.Setup(x => x.Set<PortalDomain>()).Returns(mockDomainsSet.Object);
        customDbContextMock.Setup(x => x.Set<PortalDomainRole>()).Returns(mockPortalDomanRolesSet.Object);

        ClassUnderTest = new PortalsRepository(customDbContextMock.Object);
    }
我的单元测试支持方法:

当单元测试执行有问题的方法时,我得到:

System.NullReferenceException:对象引用未设置为对象的实例


很可能它不知道如何处理嵌套的include语句-我已经学习了许多在线问题和教程,现在我陷入了困境。

我的答案可能有点争议,但根据我的经验,测试存储库层或任何你称之为实际数据访问代码的最佳方法,就是让它在测试过程中调用数据库

在编写单元测试时,您假设实体框架以特定的方式工作。但有时它的工作方式与您预期的不同,因此测试可能会通过,即使代码不能正常工作

举个例子,这说明了我使用的上一个EF版本是版本4的问题,但我假设我的声明对于EF6仍然是正确的

public class Foo {
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public bool Active {
        get { return StartDate < DateTime.Now && EndDate > DateTime.Now }
    }
}

public class FooRepository {
    public IEnumerable<Foo> ActiveFoos { get { return DataContext.Foos.Where(x => x.Active) } }
}
针对模拟数据访问测试此FooRepository将通过,但针对真实数据库执行将引发异常。这是因为EF将尝试为Wherex=>x.Active创建一个SQL子句,但由于Active不是数据库中的字段,EF将不知道如何将查询转换为SQL

所以你的单元测试提供了一个假阳性。对数据库执行测试将使其失败,这是应该的