我有一个Rails 4应用程序,这是我的lib / foobar:
jan@rmbp ~/D/r/v/l/foobar> tree
.
├── foo_bar.rb
└── foobar_spec.rb
0 directories, 2 files
文件:
foobar_spec.rb
require "spec_helper"
describe "FooBar" do
subject { FooBar.new }
its(:foo) { should == "foo"}
#stubbed version of test crashes
#FooBar.stub(:foo).and_return("bar")
#subject { FooBar.new }
#its(:foo) { should == "bar"}
end
foo_bar.rb
class FooBar
def foo
"foo"
end
end
spec_helper.rb:
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
# commented for zeus two runs bug
require 'rspec/autorun'
require 'capybara/rspec'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
# Checks for pending migrations before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
config.include Features::SessionHelpers, type: :feature
# ## Mock Framework
#
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
#
# config.mock_with :mocha
# config.mock_with :flexmock
# config.mock_with :rr
config.mock_with :rspec
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
config.infer_base_class_for_anonymous_controllers = false
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = "random"
end
规范很好。但是当我取消注释这一行时:
# FooBar.stub(:foo).and_return("bar")
失败了:
/Users/jan/.rvm/gems/ruby-2.0.0-p247/gems/rspec-mocks-2.14.3/lib/rspec/mocks.rb:26:in `proxy_for': undefined method `proxy_for' for nil:NilClass (NoMethodError)
有什么问题?
编辑:
此外,我似乎也无法使用webmock
。
stub_request(:post, "https://accounts.google.com/o/oauth2/token")
.with(:body => { "client_id" => CLIENT_ID,
"client_secret" => CLIENT_SECRET,
"refresh_token" => refresh_token, }
).to_return(:status => 200,
:body => File.read("#{$fixtures}/refresh_token.json"))
返回:
/Users/jan/Documents/ruby/vince.re/lib/youtube/you_tube_test.rb:9:in
block in <top (required)>': undefined method
stub_request'for &LT;分类:0x007f8159bbe7c0&gt; (NoMethodError)
解:
感谢@gotva告诉我有关存储在it
块内的存根要求。这是我新的固定webmock测试,它运行良好:
context "when token is nil it" do
it "called refresh method" do
YouTube.any_instance.should_receive(:refresh_auth_token).with(data["refresh"])
YouTube.new(data["uid"], nil, data["refresh"])
end
it "refreshed the authentation token" do
stub_request(:post, "https://accounts.google.com/o/oauth2/token")
.with(:body => { "client_id" => CLIENT_ID,
"client_secret" => CLIENT_SECRET,
"grant_type"=>"refresh_token",
"refresh_token" => data["refresh"], }
).to_return(:status => 200,
:body => File.read("#{$fixtures}/refresh_token.json"))
yt = YouTube.new(data["uid"], nil, data["refresh"])
yt.token.should == data["access_token"]
end
end
答案 0 :(得分:13)
在我看来,使用这个存根
FooBar.stub(:foo).and_return("bar")
你正在尝试存根不存在的方法。
方法foo
是实例方法,但你是存根类方法。
如果你想要实例方法FooBar#foo使用any_instance
FooBar.any_instance.stub(:foo).and_return("bar")
从评论中更新
在stub
或it
块中应用before
。
新变种:
it 'place here some description for method foo' do
FooBar.any_instance.stub(:foo).and_return("bar")
expect(FooBar.new.foo).to eql('bar')
end
或
# the order is important!
describe "FooBar" do
before { FooBar.any_instance.stub(:foo).and_return("bar") }
subject { FooBar.new }
its(:foo) { should == "foo"}
end