Moq +单元测试——我如何将一个Action传递给我的类来测试该Action是否被调用

本文关键字:Action 我的 测试 调用 是否 一个 单元测试 Moq | 更新日期: 2023-09-27 18:11:11

基本上,我的类上有一个方法,如果满足某些条件,则调用Action<T>。我如何进行单元测试以确保操作被调用?

public class MyClass<T>
{
    private IDBService _dbService;
    private Action<T> _action;
    public MyClass(IDBService dbService, Action<T> action)
    {
        if (dbService == null) throw new ArgumentNullException("dbService");
        if (action == null) throw new ArgumentNullException("action");
        _dbService = dbService;
        _action = action;
    }
    public void CallActionIfPossible(T param)
    {
        if (_dbService.IsTopUser)
            action(param);
    }
}

Moq +单元测试——我如何将一个Action传递给我的类来测试该Action是否被调用

基本思想是Action<T>在某处产生一些状态变化(如果没有,那又有什么意义呢?)因此,单元测试,当条件保持时,预期的状态变化发生,当条件不保持时,预期的状态变化不发生。

当然,理想情况下,您可以模拟Action<T>,这样状态测试就非常容易了。您不需要Moq或任何其他mock框架:

bool actionWasInvoked = false;
Action<Foo> action = foo => actionWasInvoked = true;
Bar<Foo> bar = new Bar<Foo>();
// set up conditions that should guarantee action is invoked
bar.M(action);
Assert.IsTrue(actionWasInvoked);

bool actionWasInvoked = false;
Action<Foo> action = foo => actionWasInvoked = true;
Bar<Foo> bar = new Bar<Foo>();
// set up conditions that should guarantee action is NOT invoked
bar.M(action);
Assert.IsFalse(actionWasInvoked);
当然,我不知道你的确切设置。也许你在Bar的构造中传递action,或者你有其他设置动作的方法。

Jason的回答很好,但是一个经常被忽略的警告是,您经常需要测试一定数量的调用(例如,不仅调用了它,而且只调用了一次)。所以我经常这样做:

var callCount = 0;
Action<Foo> action = _ => callCount++;
Bar<Foo> bar = new Bar<Foo>();
// set up conditions that should guarantee action is invoked
bar.M(action);
Assert.That(callCount, Is.EqualTo(1));