4

我有一个在 gon 的帮助下向 js 发送变量的函数。

def calc_foo
  # calculate foo
  gon.foo = foo
end

我想测试这个函数,即使用 rspec 确保该方法返回正确的值。

it "should return bar" do
  foo = @foo_controller.calc_foo
  expect(foo).to eq(bar)
end

但是,当测试用例到达变量发送到 gon 的行时,我收到以下错误消息。

Failure/Error: foo = @foo_controller.calc_foo
 NoMethodError:
   undefined method `uuid' for nil:NilClass

我检查了 foo 的值,它不是 Nil,所以 gon 必须是 Nil。我相信错误是我没有正确地包含 gon。这是我的 Gemfile 的 rspec 部分

#rspec-rails includes RSpec itself in a wrapper to make it play nicely with Rails. 
#Factory_girl replaces Rails’ default fixtures for feeding test data
#to the test suite with much more preferable factories.
group :development, :test do
  gem 'rspec-rails'
  gem 'factory_girl_rails'
  gem 'capybara'
  gem 'gon'
end

那么我怎样才能让 rspec 与 gon 很好地配合呢?(我也尝试将 gon 包含在我的规范文件中,但没有成功)

4

2 回答 2

2

在控制器规格(gon属于哪里)中,您需要提出实际请求以绕过您的问题:

RSpec.describe ThingiesController do
  let(:gon) { RequestStore.store[:gon].gon }

  describe 'GET #new' do
    it 'gonifies as expected' do
      get :new, {}, valid_session # <= this one
      expect(gon['key']).to eq :value
    end
  end
end

如果您不想坚持某些controlleraction-gon相关规范(假设您的 中有一个gon-related 方法ApplicationController),您可以使用匿名控制器方法:

RSpec.describe ApplicationController do
  let(:gon) { RequestStore.store[:gon].gon }

  controller do
    # # Feel free to specify any of the required callbacks,
    # # like
    # skip_authorization_check
    # # (if you use `CanCan`) 
    # # or
    # before_action :required_callback_name

    def index
      render text: :whatever
    end
  end

  describe '#gon_related_method' do
    it 'gonifies as expected' do
      get :index
      expect(gon['key']).to eq :value
    end
  end
end

我有很多controllerrequest/规范,只要您提出实际请求,我就integration可以确认那里的行为正常。gon

但是,尽管情况不同(从规范中shared_examples包含的请求中提出请求),但我仍然遇到与您类似的问题。controller我已经打开了相关问题,请随时加入对话(任何感兴趣的人)。

于 2015-11-23T16:11:44.777 回答
1

我测试控制器是否传递了正确的东西以进入请求规范。

控制器设置一个对象数组——例如gon.map_markers = [...]

我的请求规范通过正则表达式提取 JSON(.split()match_array处理与顺序无关的数组):

....

# match something like
#   gon.map_markers=[{"lat":a,"lng":b},{"lat":c,"lng":d},...];
# and reduce/convert it to
#   ['"lat":a,"lng":b',
#    '"lat":c,"lng":d',
#    ...
#   ]
actual_map_markers = response.body
                     .match('gon.map_markers=\[\{([^\]]*)\}\]')[1]
                     .split('},{')

expect(actual_map_markers).to match_array expected_map_markers
于 2014-10-23T13:19:37.070 回答