[英]Entity Framework 6 Unit Testing (NSubstitute) - How to test that an object with children does not return children when children are not requested
我有一個方法來使用實體框架上下文獲取雇主(禁用延遲加載)。 有時候我想要包含Employees,有時我不這樣做,因此我的數據訪問類中包含以下代碼:
public Employer GetEmployer(int employerId, bool includeRelationships)
{
Employer employer;
if (includeRelationships)
{
employer = (from e in this.context.Employers.Include(e => e.Employees)
where e.EmployerId == employerId
select e).SingleOrDefault();
}
else
{
employer = this.context.Employers.SingleOrDefault(e => e.EmployerId == employerId);
}
return employer;
}
從幾個關於如何使用NSubstitute替換EF上下文返回的問題我在我的測試項目中有這個擴展方法來連接DbSet調用替換(特別是NSubstitute DbSet / IQueryable <T> ):
public static IDbSet<T> Initialise<T>(this IDbSet<T> dbSet, IQueryable<T> data) where T : class
{
dbSet.Provider.Returns(data.Provider);
dbSet.Expression.Returns(data.Expression);
dbSet.ElementType.Returns(data.ElementType);
dbSet.GetEnumerator().Returns(data.GetEnumerator());
return dbSet;
}
然后,它用於初始化測試類中的替代雇主集:
[TestInitialize]
public void TestInitialise()
{
this.context = Substitute.For<EmployerContext>();
this.dao = new EmployerDao(this.context);
var employers = new List<Employer>();
var employerWithoutEmployee = new Employer { EmployerId = 1 };
employers.Add(employerWithoutEmployee);
var employerWithEmployee = new Employer { EmployerId = 2 };
var employee = new Employee { EmployeeId = 1, EmployerId = 2, Employer = employerWithEmployee };
employerWithEmployee.Employees.Add(employee);
employers.Add(employerWithEmployee);
this.substituteEmployers = Substitute.For<IDbSet<Employer>>().Initialise(employers.AsQueryable());
this.context.Employers.Returns(this.substituteEmployers);
}
所以,我現在有一個看起來像這樣的測試:
[TestMethod]
public void ReturnsEmployerWithNullEmployeeWhenIncludeIsFalse()
{
// Assemble
var expectedEmployer = this.substituteEmployers.First(e => e.Employees.Any();
var employerId = expectedEmployer.EmployerId;
// Act
var actualEmployer = this.dao.GetEmployer(employerId, false);
var actualEmployee = actualEmployer.Employees.FirstOrDefault();
// Assert
Assert.AreSame(expectedEmployer, actualEmployer);
Assert.IsNotNull(actualEmployer);
Assert.IsNull(actualEmployee);
this.context.Employers.ReceivedWithAnyArgs();
}
此測試在Assert.IsNull(actualEmployee);
上失敗Assert.IsNull(actualEmployee);
在實際使用中,GetEmployer將返回沒有Employee子女的雇主。
但是,因為我用雇員代替雇主(因為這是我正在測試的!),該方法返回具有Employee的替代品。
我該怎么測試呢?
或者,我測試不正確嗎?
我是否應該使用沒有員工的雇主,因為這是上下文會返回的內容?
但那不會使測試毫無意義!?!
我在這里思考自己......
很多時候我試圖用不同的技術來模擬DbContext。 但每當我想到“是的,這次它的表現就像真正的EF!” 我發現了另一個用例,當mock不像真實的東西那樣。 通過模擬進行的測試確實會讓您產生錯誤的信心。 但是當生產中發生相同的操作時,您會遇到異常和錯誤。
所以我的結論是停止嘗試模擬DbContext並進行集成測試。 設置有點問題,但設置逼真的模擬需要更多的時間! 我寫過關於如何在我的博客中進行無故障集成測試的文章: http : //tech.trailmax.info/2014/03/how-we-do-database-integration-tests-with-entity-framework-遷移/
現在我傾向於編寫很多集成測試(對於CRUD的東西),這些測試實際上是進入DB而且很糟糕。 為您提供更多保證(而不是使用db-mock),相同的操作將在生產中起作用。
不是你的問題的答案。 只是我的.02 $
這是不可能的。 這是EF“內存中”測試模型的限制。 有關詳細信息,請參閱此文
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.