使用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中。
答案 0 :(得分:2)
使用开源工具测试Linq to SQL并不是最简单的方法。希望这种方法对你有用。
FakeItEasy没有像JustMock的ReturnCollection那样的方法,它允许你模拟ITable来返回IEnumerable。您可以选择创建一个类似于here所示的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);
}
我实际上没有编译过这个,但概念应该是稳定的。依赖抽象将使您的代码更易于测试并且更容易模拟。
希望这有所帮助。
答案 1 :(得分:2)
我使用FakeItEasy完成此操作的方法是向DataContext添加一个接口,并将其用作我的repos中的依赖项。 E.g。
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
。