起订量 +单元测试——如何将一个操作传递给我的类来测试该操作是否被调用?

发布于 2024-12-09 10:29:45 字数 618 浏览 0 评论 0原文

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

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);
    }
}

Basically, I have a method on my class that invokes an Action<T> if certain conditions are met. How can I unit test to ensure that the action is invoked?

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);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

豆芽 2024-12-16 10:29:45

好吧,基本思想是 Action 在某处产生一些状态变化(如果没有,那有什么意义?)。因此,单元测试当条件成立时预期的状态更改会发生,而当条件不成立时预期的状态更改不会发生。

当然,理想情况下,您可以模拟 Action ,以便状态测试非常简单。您不需要 Moq 或任何其他模拟框架:

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,或者您可能有其他设置操作的方法。但这个想法应该很清楚。

Well, the basic idea is that the Action<T> produces some state change somewhere (if it doesn't, what's the point?). So, unit test that the expected state change occurs when the conditions hold, and that the expected state change doesn't occur when the conditions do not hold.

Of course, ideally, you mock the Action<T> so that the state testing is super easy. You do not need Moq or any other mocking framework for this:

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);

and

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);

Of course, I don't know your exact setup. Maybe you pass in action on construction of Bar, or maybe you have some other way of setting the action. But the idea should be clear.

蓝咒 2024-12-16 10:29:45

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));

Jason's answer is good, but one caveat that is often overlooked is that you will often need to test for a certain number of invocations (e.g. not only was it called, but it was called exactly once). So I often do something like this:

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));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文