我有一个 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 < Class :0x007f8159bbe7c0> (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