Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.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
Entity framework 使用OF类型_Entity Framework_Unit Testing_Extension Methods_Dbset - Fatal编程技术网

Entity framework 使用OF类型

Entity framework 使用OF类型,entity-framework,unit-testing,extension-methods,dbset,Entity Framework,Unit Testing,Extension Methods,Dbset,我试图遵循微软提供的单元测试dbset的指导原则。正如他们记录的那样,一切进展顺利。直到我找到了一些可以使用继承表的代码。因为OfType是一种扩展方法,所以我不知道如何创建一个模拟来保持代码的可测试性 澄清一下:我正在尝试测试我的服务层,它采用注入的DBContext,并公开几个dbset。特别是,我有一个抽象的历史类,它有StaffHistory、ContactHistory等具体的派生类型。因此,我的Dbcontext上只有1个DbSet,属于History类型。然后,我使用类型的扩展方法

我试图遵循微软提供的单元测试dbset的指导原则。正如他们记录的那样,一切进展顺利。直到我找到了一些可以使用继承表的代码。因为OfType是一种扩展方法,所以我不知道如何创建一个模拟来保持代码的可测试性

澄清一下:我正在尝试测试我的服务层,它采用注入的DBContext,并公开几个dbset。特别是,我有一个抽象的历史类,它有StaffHistory、ContactHistory等具体的派生类型。因此,我的Dbcontext上只有1个DbSet,属于History类型。然后,我使用类型的扩展方法来设置鉴别器并查询特定类型

当我创建一个模拟数据库集时,除了OfType扩展方法失败,报告NullReference异常外,其他所有方法都正常工作

有什么想法或建议吗

服务层:

public IEnumerable<ContactHistory> GetContactHistory(int ContactId, int AgeInDays)
{
    var age = DateTimeOffset.Now.AddDays(-Math.Abs(AgeInDays));
    return context.History.OfType<ContactHistory>()
        .Where(h => h.ContactId == ContactId && h.CreatedAt >= age)
        .AsEnumerable();
}
单元测试代码:

[TestMethod]
public void History_Returns_Limited_Results()
{
    var testData = new List<ContactHistory> {
        new ContactHistory {
            ContactId = 1,
            CreatedAt = DateTimeOffset.Now,
            UserName = "UserA",
            Action = "Action",
        },
        new ContactHistory {
            ContactId = 4,
            CreatedAt = DateTimeOffset.Now.AddDays(-61),
            UserName = "UserA",
            Action = "Action",
        },
        new ContactHistory {
            ContactId = 4,
            CreatedAt = DateTimeOffset.Now.AddDays(-60),
            UserName = "UserA",
            Action = "Action",
        },
        new ContactHistory {
            ContactId = 4,
            CreatedAt = DateTimeOffset.Now,
            UserName = "UserA",
            Action = "Action",
        }
    }.AsQueryable();

    // Setup
    var mockContext = new Mock<IPEContext>();
    var mockSet = new Mock<IDbSet<History>>();
    mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.Provider).Returns(testData.Provider);
    mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.Expression).Returns(testData.Expression);
    mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.ElementType).Returns(testData.ElementType);
    mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.GetEnumerator()).Returns(testData.GetEnumerator());

    mockContext.Setup(c => c.History).Returns(mockSet.Object);

    // Test
    var service = new HistoryService(mockContext.Object);
    var historyFound = service.GetContactHistory(4, 60);

    // Verify
    Assert.IsNotNull(historyFound);
    Assert.AreEqual(2, historyFound.Count());
}

我的方法有缺陷吗?我设置模拟的方式是否有缺陷?这是我上面提到的Microsoft文章的后续内容,这样我就可以测试作用于DbSet的服务逻辑。唯一的缺陷似乎是扩展方法-不确定我应该如何解决这个问题。

好的-我已经解决了这个问题。当然有一个简单的答案,但我没有找到,因为我已经将Linq提供程序和all映射为IQueryable类型。如果您使用的是.OfType方法,则模拟必须返回非类型化的Queryable方法

以下是允许该方法正常工作的测试代码:

    [TestMethod]
    public void History_Returns_Limited_Results()
    {
        var today = new DateTimeOffset(DateTime.Today, DateTimeOffset.Now.Offset);
        var testData = new List<ContactHistory> {
            new ContactHistory {
                ContactId = 1,
                CreatedAt = today,
                UserName = "UserA",
                Action = "Action",
            },
            new ContactHistory {
                ContactId = 4,
                CreatedAt = today.AddDays(-61),
                UserName = "UserA",
                Action = "Action",
            },
            new ContactHistory {
                ContactId = 4,
                CreatedAt = today.AddDays(-60),
                UserName = "UserA",
                Action = "Action",
            },
            new ContactHistory {
                ContactId = 4,
                CreatedAt = today,
                UserName = "UserA",
                Action = "Action",
            }
        }.AsQueryable();

        // Setup
        var mockContext = new Mock<IPEContext>();
        var mockSet = new Mock<IDbSet<History>>();
        mockSet.As<IQueryable>().Setup(m => m.Provider).Returns(testData.Provider);
        mockSet.As<IQueryable>().Setup(m => m.Expression).Returns(testData.Expression);
        mockSet.As<IQueryable>().Setup(m => m.ElementType).Returns(testData.ElementType);
        mockSet.As<IQueryable>().Setup(m => m.GetEnumerator()).Returns(testData.GetEnumerator());
        mockContext.Setup(c => c.History).Returns(mockSet.Object);

        // Test
        var service = new HistoryService(mockContext.Object);
        var contact = new Person { ContactId = 4 };
        var historyFound = service.GetContactHistory(contact, 60);

        // Verify
        Assert.IsNotNull(historyFound);
        Assert.AreEqual(2, historyFound.Count());
    }

您不应该模拟类型,您应该以这样一种方式设置数据,使代码能够按预期工作。您可以提供一个示例吗?以下是我试图为其构建测试的服务方法:public IEnumerable GetClientHistoryClient客户端,int-AgeInDays{var age=DateTimeOffset.Now.AddDays-Math.AbsAgeInDays;返回context.History.OfType。其中h=>h.ClientId==Client.ClientId&&h.CreatedAt>=age.AsEnumerable;}你应该通过正确填充History属性来传递客户端对象。我猜History是一个集合,因此你应该在那里有一些ClientHistory类型的对象和一些其他不匹配的对象。请重新阅读我的问题,如果你能解释最后一条注释,使其有意义,我将不胜感激。我不想填充正如我认为您所建议的,附加实体的ICollection属性-我想执行一个单独的唯一查询。