40

rspec 文档中指出我应该使用double方法来创建测试替身。但是我可以看到即使我不使用它也可以正常工作double。不使用有什么问题double吗?另外,如果我不使用 double 如何MyClass获取stub和其他 rspec 方法?在 rspec 中运行时它们是否可用于所有对象?

require 'spec_helper'

class MyClass

    def self.run
        new.execute
    end

    def execute
        'foo'
    end

end

describe MyClass do

    it 'should stub instance method' do
        obj = MyClass.new
        obj.stub(:execute).and_return('bar')
        obj.execute.should == 'bar'
    end

    it 'should stub class method' do
        MyClass.stub(:run).and_return('baz')
        MyClass.run.should == 'baz'
    end

end
4

2 回答 2

47

编辑:我刚刚重读了你的问题,并意识到我没有完全回答它。留下我原来的答案,因为它是相关的,但这是你的具体答案:

您不需要双精度的原因是因为您正在存根类方法,而不是实例方法。 double仅用于处理类的实例,而不是类本身。

旧答案解释了更多:

你应该尽可能地使用真正的类而不是测试替身。这将锻炼更多的代码并使您的测试更加全面。测试替身用于您不能或不应该使用真实对象的情况。例如,如果一个类在不访问外部资源(如网络或数据库)的情况下无法实例化,或者具有大量依赖项,而您只是在测试使用它的东西,您可能想要创建一个double 和 stub 上的一些方法。

这是一个更具体的示例:假设您正在 testing MyClass,但是为了实例化MyClass,您需要传入 a FooLogger

mylogger = FooLogger.new
myclass = MyClass.new logger: mylogger

如果FooLogger.new打开一个 syslog 套接字并立即开始向其发送垃圾邮件,则每次运行测试时,您都会记录日志。如果您不想在此测试期间向您的日志发送垃圾邮件,则可以改为创建一个 double forFooLogger并在其上存根一个方法:

mylogger = double(FooLogger)
mylogger.stub(:log)
myclass = MyClass.new logger: mylogger

因为大多数设计良好的类都可以在没有任何副作用的情况下实例化,所以您通常可以只使用真实对象而不是双精度对象,并在其上使用存根方法。在其他情况下,类有许多依赖项,使它们难以实例化,而双打是一种克服麻烦并测试你真正关心的东西的方法。

根据我的经验,需要使用 double 是一种代码味道,但我们经常不得不使用我们无法轻易更改的类(例如来自 gem),因此它是您可能不时需要的工具。

于 2013-03-06T16:25:48.873 回答
-1

在 RSpec Mocks 3.0 中,双打的行为发生了变化。您现在可以验证 doubles,这意味着“RSpec 将检查被存根的方法是否实际存在于基础对象上(如果它可用)”,但“如果未定义基础对象或类,则不会进行检查”。

验证双精度要求您具体了解双精度类型(实例、类、对象、动态类、部分)。下面是RSpec Relish中的一个实例双精度示例:

RSpec.describe User, '#suspend!' do
  it 'notifies the console' do
    notifier = instance_double("ConsoleNotifier")

    expect(notifier).to receive(:notify).with("suspended as")

    user = User.new(notifier)
    user.suspend!
  end
end
于 2014-06-09T07:52:37.440 回答