2

使用JustMock,我可以像这样轻松地在 Linq to SQL 中模拟带有列表的 DataContext 表,其中一个 IEnumerable 通过 ReturnsCollection() 代替每个 DataContext 的表,允许我插入假数据:

[TestMethod]
public void ShouldGetManagersByHireDate()
{
   var context = Mock.Create<MyDataContext>();
   Mock.Arrange(()=> context.Employees).ReturnsCollection(GetFakeEmployees());
   Mock.Arrange(() => context.Managers).ReturnsCollection(GetFakeManagers());

   var repository = new EmployeeRepository(context);
   var managers = repository.GetManagersByHireDate(new DateTime(2002, 1, 1), DateTime.Now);

   Assert.AreEqual(1, managers.Count());
   Assert.AreEqual(1, managers.FirstOrDefault().ID);
}

private IEnumerable<Employee> GetFakeEmployees()
{
    return new List<Employee> { 
        new Employee { ID = 1, HireDate = new DateTime(2004, 12, 1) }, 
        new Employee { ID = 2, HireDate = new DateTime(2006, 7, 1) }, 
        new Employee { ID = 3, HireDate = new DateTime(2009, 3, 1) } 
    };
}

private IEnumerable<Manager> GetFakeManagers()
{
    return new List<Manager> { 
        new Manager { ID = 1 }
    };
}

这将是正在测试的方法:

public IQueryable<Employee> GetManagersByHireDate(DateTime start, DateTime end)
{
    return  from e in context.Employees
            join m in context.Managers on e.ID equals m.ID
            where e.HireDate >= start && e.HireDate <= end
            select e;
}

我正在寻找某种方式来执行相同的魔法,让我可以IEnumerable<T>代替Table<T>用于测试 Linq to SQL 的目的,最好是在 FakeItEasy 中。

4

2 回答 2

2

Linq to SQL 并不是使用开源工具测试的最简单的东西。希望这种方法对您有用。

FakeItEasy 没有与 JustMock 的 ReturnCollection 完全相同的方法,它允许您模拟 ITable 以返回 IEnumerable。您拥有的一种选择是创建一个类似于此处所示的 MockableTable 。然后填充你的表,你可以有类似的东西

private ITable<Employee> GetFakeEmployees() {
    List<Employee> sampleData = /* fill it up with employees */
    var employeeTable = new MockableTable<Employee>(null, sampleData.AsQuerable());                 
    return employeeTable;
}

此外,FakeItEasy 不会拦截 DataContext 上的 Employees 属性,因为它是具体类上的非虚拟属性。您可以创建一个简单的自定义基类并让 MyDataContext 类直接从中派生。

public abstract class CustomDataContext : DataContext, ICustomDataContext {
}

public interface ICustomDataContext {
    ITable<Employee> { get; }
}

这里的要点是利用接口进行模拟。然后在您的测试方法中,您将拥有:

[TestMethod]
public void ShouldGetManagersByHireDate() {
   var context = A.Fake<ICustomDataContext>();
   A.CallTo(()=> context.Employees).Returns(GetFakeEmployees());


   var repository = new EmployeeRepository(context);
   var managers = repository.GetManagersByHireDate(new DateTime(2002, 1, 1), DateTime.Now);

   Assert.AreEqual(1, managers.Count());
   Assert.AreEqual(1, managers.FirstOrDefault().ID);
}

我实际上并没有编译这个,但概念应该是稳定的。依赖抽象将使您的代码更易于测试和模拟。

希望这会有所帮助。

于 2013-02-22T21:34:57.713 回答
2

我使用 FakeItEasy 完成此操作的方法是向 DataContext 添加一个接口,并将其用作我的 repos 中的依赖项。例如

public interface IMyDataContext : IDisposable
{
    IQueryable<Employee> Employees { get; }

    // etc.
}

public partial class MyDataContext: IMyDataContext
{
    IQueryable<Message> IMyDataContext.Employees
    {
        get { return this.Employees; }
    }

    // etc.
}

public class EmployeeRepository
{
    public EmployeeRepository(IMyDataContext context)
    {
        // etc.
    }
}

在我的测试中:

var context = A.Fake<IMyDataContext>();
A.CallTo(() => context.Employees).Returns(new[] { new Employee { Name = "John", Name = "Fred" }.AsQueryable());
var repository = new EmployeeRepository(context)

我认为不需要任何考虑ITable

于 2013-04-02T09:37:54.727 回答