簡體   English   中英

實體框架6單元測試(NSubstitute) - 如何測試帶有孩子的對象在沒有請求孩子時不返回孩子

[英]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“內存中”測試模型的限制。 有關詳細信息,請參閱此文

https://msdn.microsoft.com/en-us/data/dn314429#limitations

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM