【问题标题】:Refactoring duplicate code that differs by type重构因类型而异的重复代码
【发布时间】:2016-03-25 01:33:28
【问题描述】:

我构建了一些测试辅助方法,为实体框架构建模拟 DBContext。这些方法包含重复的代码,我假设必须有更好的方法来做到这一点。我只是不知道怎么做。我尝试创建一个 MockDbContextBuilder 类,但失败了,因为我没有 DbSet。有任何想法吗?以下是我尝试重构为一种方法的三个示例:

    private Mock<IPSNContext> BuildMockDbContext(List<TestEntity> list)
    {
        _mockDbSet = new Mock<DbSet<TestEntity>>();
        _mockDbSet.As<IQueryable<TestEntity>>().Setup(m => m.Provider).Returns(list.AsQueryable().Provider);
        _mockDbSet.As<IQueryable<TestEntity>>().Setup(m => m.Expression).Returns(list.AsQueryable().Expression);
        _mockDbSet.As<IQueryable<TestEntity>>().Setup(m => m.ElementType).Returns(list.AsQueryable().ElementType);
        _mockDbSet.As<IQueryable<TestEntity>>().Setup(m => m.GetEnumerator()).Returns(list.AsQueryable().GetEnumerator());

        foreach (var item in list)
        {
            _mockDbSet.Setup(m => m.Find(item.Id)).Returns(item);
        }

        var mockContext = new Mock<IPSNContext>();
        mockContext.Setup(c => c.Set<TestEntity>())
                    .Returns(_mockDbSet.Object);
        return mockContext;
    }

    private Mock<IPSNContext> BuildMockDbContext(List<MessageBoardTopic> list)
    {
        _mockDbSet = new Mock<DbSet<MessageBoardTopic>>();
        _mockDbSet.As<IQueryable<MessageBoardTopic>>().Setup(m => m.Provider).Returns(list.AsQueryable().Provider);
        _mockDbSet.As<IQueryable<MessageBoardTopic>>().Setup(m => m.Expression).Returns(list.AsQueryable().Expression);
        _mockDbSet.As<IQueryable<MessageBoardTopic>>().Setup(m => m.ElementType).Returns(list.AsQueryable().ElementType);
        _mockDbSet.As<IQueryable<MessageBoardTopic>>().Setup(m => m.GetEnumerator()).Returns(list.AsQueryable().GetEnumerator());

        foreach (var item in list)
        {
            _mockDbSet.Setup(m => m.Find(item.Id)).Returns(item);
        }

        var mockContext = new Mock<IPSNContext>();
        mockContext.Setup(c => c.Set<MessageBoardTopic>())
                    .Returns(_mockDbSet.Object);        
        return mockContext;
    }

    private Mock<IPSNContext> BuildMockDbContext(List<MessageBoardReply> list)
    {
        _mockDbSet = new Mock<DbSet<MessageBoardReply>>();
        _mockDbSet.As<IQueryable<MessageBoardReply>>().Setup(m => m.Provider).Returns(list.AsQueryable().Provider);
        _mockDbSet.As<IQueryable<MessageBoardReply>>().Setup(m => m.Expression).Returns(list.AsQueryable().Expression);
        _mockDbSet.As<IQueryable<MessageBoardReply>>().Setup(m => m.ElementType).Returns(list.AsQueryable().ElementType);
        _mockDbSet.As<IQueryable<MessageBoardReply>>().Setup(m => m.GetEnumerator()).Returns(list.AsQueryable().GetEnumerator());

        foreach (var item in list)
        {
            _mockDbSet.Setup(m => m.Find(item.Id)).Returns(item);
        }

        var mockContext = new Mock<IPSNContext>();
        mockContext.Setup(c => c.Set<MessageBoardReply>())
                    .Returns(_mockDbSet.Object);
        return mockContext;
    }

【问题讨论】:

    标签: c# oop generics inheritance refactoring


    【解决方案1】:

    你可以有一个泛型类型的方法,像这样:

        private Mock<IPSNContext> BuildMockDbContext<T>(List<T> list)
        {
                    _mockDbSet = new Mock<DbSet<T>>();
                    _mockDbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(list.AsQueryable().Provider);
                    _mockDbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(list.AsQueryable().Expression);
                    _mockDbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(list.AsQueryable().ElementType);
                    _mockDbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(list.AsQueryable().GetEnumerator());
    
                    foreach (var item in list)            
                        _mockDbSet.Setup(m => m.Find(item.Id)).Returns(item);            
    
                    var mockContext = new Mock<IPSNContext>();
                    mockContext.Setup(c => c.Set<MessageBoardTopic>())
                                .Returns(_mockDbSet.Object);
    
                    return mockContext;
       }
    

    【讨论】:

    • 这行得通。谢谢。因为 DbSet 期望 T 是一个类,我只需要添加 private Mock BuildMockDbContext(List list) where TEntity : class, new()跨度>
    猜你喜欢
    • 1970-01-01
    • 2017-08-01
    • 2023-04-07
    • 1970-01-01
    • 2014-01-07
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多