2

我正在尝试学习如何使用 FakeItEasy,并想尝试将它与我有权访问的旧项目中的一些数据访问代码一起使用。虽然 FIE 的基础知识看起来很​​简单,而且我能够处理简单的案例,但这让我很难过。

该系统使用实体框架,其中一个数据管理类处理用户,我试图弄清楚如何仅测试基本GetUserByUserNumber功能。我可以在实例化 UserDataManager 类时使用假IPersistenceManager<User>的,然后调用该GetUserByUserNumber方法,但是检查userPersistenceManager.ReadCustom被调用的断言总是失败。

我尝试在 fake 上调用 Delete 方法userPersistenceManager,并且该断言工作正常。我认为这与该ReadCustom方法作为其第一个参数的 Linq 表达式有关。我只是不知道应该如何处理。对此的任何帮助将不胜感激!

这是我正在尝试测试的 UserDataManager 中的方法:

public User GetUserByUserNumber(string userNumber, bool loadRelatedRecords = false)
{
    if (string.IsNullOrWhiteSpace(userNumber))
    {
        throw MyAppExceptions.CreateMyAppFatalException(Constants.ExceptionKeys.Unexpected, new ArgumentNullException("userNumber"));
    }
    Logger.Write(string.Format("Executing GetUserByUserNumber with UserNumber {0}.", userNumber), LogCategory.General, TraceEventType.Verbose);
    return _UserPersistenceManager.ReadCustom(mem => mem.UserNumber == userNumber, EntityConstants.EntityNames.UserDetail);
}

这是我要确保调用的 IPersistenceManager 方法:

TEntity ReadCustom(Expression<Func<TEntity, bool>> predicate, string includeEntityName);

这是我的单元测试:

[TestMethod]
public void GetUserByUserNumber_Calls_ReadCustom()
{
    // Arrange
    var userPersistenceManager = A.Fake<IPersistenceManager<User>>();
    var dataManager = new UserDataManager(userPersistenceManager);

    // Act
    dataManager.GetUserByUserNumber("123456", false);

    // Assert
    A.CallTo(() => userPersistenceManager.ReadCustom(u => u.UserNumber == "123456", EntityConstants.EntityNames.UserDetail)).MustHaveHappened();
}
4

2 回答 2

1

我认为 Tim Long 的回答基本上是正确的,尽管我的观点不是这是模拟框架的失败——它归结为确定两件事是否“相同”是多么容易(通常,不仅仅是在模拟时)。

您遇到的问题是,除非另有说明,否则 FakeItEasy 用于.Equals比较参数。Expressions 不能很好地与 比较.Equals,所以你会得到一个不匹配的结果。一种选择是探索Expression平等检查器。StackOverflow 上已经有很多关于此的问题,例如如何检查两个 Expression<Func<T, bool>> 是否相同。如果您能找到确定表达式相等性的好方法,我认为您可以将该方法提供给 FakeItEasy 的参数匹配器
(例如 with A<Expression<Func<TEntity, bool>>.That.Matches(…))。

或者,你也可以走龙先生的路线,抓住争论,然后再审问。刚才在回答How to fake an action<> with FakeItEasy时,我提出了类似的方法 。

在您的情况下,您可以捕获谓词,然后通过查看它对各种输入对象的反应来验证它的正确性 - 它是否像带有UserNumber“123456”的那些。

于 2013-11-30T11:54:54.087 回答
1

这似乎是一个非常违反直觉且难以正确使用的模拟框架领域。我通常会回避进行参数匹配,并尝试返回或捕获某种我以后可以对其进行断言的对象。

在您的情况下,您实际上是在比较两个表达式是否相等。即使它们具有相同的语法,代码中的“外观”也不同。我想知道,您能否在测试上下文之外创建这两个表达式,然后看看它们是否相等?

于 2013-11-30T04:42:00.993 回答