ruby rspec 中的双重方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15252314/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 05:48:40  来源:igfitidea点击:

What is double method in rspec for?

rubyrspecmockingstub

提问by grafthez

It is stated in rspec doc that I should use doublemethod in order to create test double. But I can see that it works perfectly ok even if I don't use double. Is there anything wrong with not using double? Also if I'm not using double how MyClassgets stuband other rspec methods? Are they available for all objects when running in rspec?

在 rspec doc 中声明我应该使用doublemethod 来创建测试替身。但我可以看到,即使我不使用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

回答by Jim Stewart

Edit: I just reread your question and realized I didn't quite answer it. Leaving my original answer because it's related, but here's your specific answer:

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

The reason you don't need a double is because you're stubbing class methods, rather than instance methods. doubleis only useful for dealing with instances of the class, not the class itself.

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

Old answer that explains double some more:

旧答案解释了更多:

You should always use real classes instead of test doubles when you can. This will exercise more of your code and make your tests more comprehensive. Test doubles are used in situations where you can't or shouldn't use a real object. For example, if a class can't be instantiated without hitting an external resource (like a network or a database), or has a large number of dependencies, and you're just testing something that uses it, you might want to create a double and stub some methods on the double.

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

Here's a more specific example: let's say you are testing MyClass, but in order to instantiate MyClass, you need to pass in a FooLogger:

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

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

If FooLogger.newopens a syslog socket and starts spamming it right away, every time you run your tests, you'll be logging. If you don't want to spam your logs during this test, you can instead create a double for FooLoggerand stub out a method on it:

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

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

Because most well-designed classes can be instantiated without any side-effects, you can usually just use the real object instead of a double, and stub methods on that instead. There are other scenarios where classes have many dependencies that make them difficult to instantiate, and doubles are a way to get past the cruft and test the thing you really care about.

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

In my experience, needing to use a double is a code smell, but we often have to use classes that we can't easily change (e.g. from a gem), so it's a tool you might need from time to time.

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

回答by georgschlenkhoff

With RSpec Mocks 3.0 the behaviour of doubles has changed. You now may verify doubles, which means "RSpec will check that the methods being stubbed are actually present on the underlying object if it is available", but "no checking will happen if the underlying object or class is not defined".

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

Verifying doubles requests you to be specific about the double type (instance, class, object, dynamic class, partial). Here is an example from the RSpec Relishfor an instance double:

验证双精度要求您具体说明双精度类型(实例、类、对象、动态类、部分)。这是来自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