如何使用RhinoMocks测试带有特定参数的方法调用

本文关键字:参数 方法 调用 何使用 RhinoMocks 测试 | 更新日期: 2023-09-27 17:53:46

我使用RhinoMocks进行模拟/存根,使用Nunit框架进行单元测试。

我有以下类

    class A
    {
        private int data = -1;
        public void Initialize (int data)
        {
            this.data = data;
        }
        public void CallA()
        {
            if (data == -1) throw new InvalidArgumentException("data has invalid value -1");
            try
            {
                A1("a1");
                A2("a2");
            }
            catch (AException e)
            {
                throw;
            }  
            catch (Exception e)
            {
                throw new AException(ErrorCode.UnknownException, e);
            }  
        }
        private void A1(string item)
        {
        }
        private void A2(string item)
        {
        }
    }

我正在努力以下测试用例:

  1. InvalidAgrumentException:如果没有调用Initialized方法或将-1作为参数传递给Initialized,则会引发该异常。数据是私有的,所以不能被模拟(除非使用TypeMock isolater之类的库来进行IL编织)。要提出此异常,一种选择是调用Initialized方法,我不确定这是正确的方法?(因为数据也可以从其他地方设置为-1。虽然这不是问题,但它需要额外的函数调用。

  2. 验证调用A1时参数为" A1 ",调用A2时参数为" A2 "

如何使用RhinoMocks测试带有特定参数的方法调用

Daniel说得很好,我只是想扩展一下他的回答。让您的测试依赖于私有方法调用会创建一个非常脆弱的测试套件。私有方法是实现的细节,你应该总是安全地改变它们,相对于内部实现的变化,而不是观察到10-20个测试失败。

Initilize方法的另一个要点—如果很难测试,想象一下使用您的类有多困难。罗伯特·马丁在他的一本书中提出了一个很好的观点,这个方法并没有说明其他方法应该以什么顺序被调用。

例如,在您的例子中,public void CallA()没有说明为什么何时调用Initialize以及使用什么参数。为什么不从Initialize创建一个带有输入参数的构造函数,或者从构造函数调用Initialize呢?现在你确定它已经被命名了。另一点是关于幻数-1

很抱歉批评,但是我曾经使用过这样的设计,并且无论您使用什么测试框架,都很难测试它们。您可以模拟private方法,您可以存根静态方法调用,但这一切都以良好的设计而告终,而不是模拟框架的力量。

你不能那样做。

mock框架用于模拟你想要测试的类的依赖关系。模拟类本身是没有意义的,因为这意味着你测试的是一个模拟而不是你的类。

此外,验证类中的私有方法是否被调用也是不正确的。您需要通过其他方式验证,两种常见的方法是:

  1. 验证类是否处于正确的状态
  2. 验证模拟依赖项上的某个方法是否被调用
您可以并且应该使用哪一个主要取决于您想要测试的类。