重构因类型而异的重复代码
Refactoring duplicate code that differs by type
我构建了一些测试辅助方法,为 entity framework 构建了一个模拟 DBContext。这些方法包含重复代码,我假设必须有更好的方法来执行此操作。我只是想不通怎么办。我尝试创建 MockDbContextBuilder<> class,但失败了,因为我没有 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;
}
您可以使用泛型类型的方法,例如:
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;
}
我构建了一些测试辅助方法,为 entity framework 构建了一个模拟 DBContext。这些方法包含重复代码,我假设必须有更好的方法来执行此操作。我只是想不通怎么办。我尝试创建 MockDbContextBuilder<> class,但失败了,因为我没有 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;
}
您可以使用泛型类型的方法,例如:
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;
}