【问题标题】:RSpec fail in POST with error: failure/Error does not implement: callRSpec 在 POST 中失败并出现错误:失败/错误未实现:调用
【发布时间】:2020-02-12 12:38:00
【问题描述】:

我正在尝试测试来自 Slack API 的方法 postMessage 端点,该端点负责在 Slack 上发送消息。

如您所见,这是一个简单的 HTTPost 请求:

module Slack
  class Messenger
    def initialize(event)
      @event = event
    end

    def call
      HTTParty.post('https://slack.com/api/chat.postMessage', body: params, headers: headers)
    end

    private

    attr_reader :event

    def params
      {
        token: Settings.slack_token,
        channel: Slack::GetUserId.new(parsed_email).call,
        text: Slack::ReporterTextMessage.new(parsed_name, parsed_ticket_number).call,
        as_user: true
      }
    end
#here are methods: parsed_email, parsed_name, parsed_ticket_number

所以我做了 RSpec 测试:

RSpec.describe Slack::Messenger do
  subject { described_class.new(event) }
  let(:event) { File.new('./spec/support/events/event.json').read }

  describe 'call' do
    let(:valid_params) do
      {
        token: 'token',
        channel: '12345',
        text: 'This is a message',
        as_user: true
      }
    end
    let(:response) { subject.call }
    before do
      allow(HTTParty).to receive(:post).and_return(valid_params)
    end

    it "returns specific params" do
      allow_any_instance_of(Slack::SlackMessenger).to receive(:call).and_return(valid_params)
      expect(response).to receive(:call).with(valid_params)
    end
  end
end

我的模拟很糟糕,因为我遇到了一个错误:

 Failure/Error: expect(response).to receive(:call).with(valid_params)
   {:token=>"token", :channel=>"12345", :text=>"This is a message", :as_user=>true} does not implement: call

编辑: 嘲笑后我得到一个错误:

1) Slack::SlackMessenger call call HTTParty
   Failure/Error: subject.call

   TypeError:
     no implicit conversion of nil into String
   # /Users/usr/.rvm/gems/ruby-2.5.0/gems/json-2.2.0/lib/json/common.rb:156:in `initialize'
   # /Users/usr/.rvm/gems/ruby-2.5.0/gems/json-2.2.0/lib/json/common.rb:156:in `new'
   # /Users/usr/.rvm/gems/ruby-2.5.0/gems/json-2.2.0/lib/json/common.rb:156:in `parse'
   # ./source/parsers/jira_parser.rb:9:in `initialize'
   # ./source/slack/messenger.rb:30:in `new'
   # ./source/slack/messenger.rb:30:in `parsed_email'
   # ./source/slack/messenger.rb:23:in `params'
   # ./source/slack/messenger.rb:13:in `call'
   # ./spec/source/slack/messenger_spec.rb:56:in `block (3 levels) in <top (required)>'

【问题讨论】:

  • 看起来很不清楚
  • 您到底想测试什么?哪种方法/方法?
  • 我想测试 call 方法,它很简单 HTTParty.post 请求,但正如您在 body: 中看到的那样,我传递的东西很少。附加参数 - channel: 和 text: 正在调用两种方法:Slack::GetUserId.new(parsed_email).call 我希望收到 SlackId(例如'12345'); Slack::ReporterTextMessage.new 负责准备 Slack 消息文本,所以我希望收到一些消息(例如 'This is a message')。我想 params 哈希可以被嘲笑。
  • 您确定HTTParty 在收到#post 后应该返回valid_params?
  • 如果您需要在调用服务时检查HTTParty 调用,那么规范应该以另一种方式显示

标签: ruby rspec


【解决方案1】:

我觉得应该是这样的:

RSpec.describe Slack::Messenger do
  subject { described_class.new(event) }
  let(:event) { File.new('./spec/support/events/event.json').read }

  describe 'call' do
    before do
      allow(HTTParty).to receive(:post).with(any_args)
    end

    it "call HTTParty" do
      subject.call
      expect(HTTParty).to have_received(:post)
    end
  end
end

但我建议存根这些参数:

def params
  {
    token: Settings.slack_token,
    channel: Slack::GetUserId.new(parsed_email).call,
    text: Slack::ReporterTextMessage.new(parsed_name, parsed_ticket_number).call,
    as_user: true
  }
end

让它看起来像:

RSpec.describe Slack::Messenger do
  subject { described_class.new(event) }
  let(:event) { File.new('./spec/support/events/event.json').read }

  describe 'call' do
    let(:slack_url) { 'https://slack.com/api/chat.postMessage' }
    let(:valid_params) do
      {
        token: 'token',
        channel: '12345',
        text: 'This is a message',
        as_user: true
      }
    end

    before do
      allow(Settings).to receive(:slack_token).and_return(valid_params[:token])
      ...
      allow(HTTParty).to receive(:post).with(slack_url, body: valid_params, header: ..)
    end

    it "call HTTParty with valid params" do
      subject.call
      expect(HTTParty).to have_received(:post).with(slack_url, body: valid_params, header: ..)
    end
  end
end

【讨论】:

  • 在这两种情况下我都会收到1) Slack::Messenger call call HTTParty with valid params Failure/Error: subject no implicit conversion of nil into String
  • 好的,我认为问题出在body: params - 例如如何模拟channel: Slack::GetUserId.new(parsed_email).call?
  • @mr_muscle allow_any_instance_of(Slack::GetUserId).to receive(:call).and_return(..) 它的捷径,但不是最好的
  • 它不起作用,但问题出在 params 模拟中,因为当我从测试类中删除所有参数(令牌除外)时,我将能够查看 params 内部的内容(在添加 pry 之后在发出请求之前)。问题是如何模拟所有其他参数
猜你喜欢
  • 2018-02-24
  • 2015-04-13
  • 1970-01-01
  • 2012-09-24
  • 2014-08-02
  • 2011-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多