简体   繁体   中英

How to test ruby module methods with block using Rspec?

I want to test a following method, which calls a module method with a block.

def test_target
  MyModule.send do |payload|
    payload.my_text = "payload text"
  end
end

MyModule 's structure is like following.

module MyModule
  class Payload
    attr_accessor :my_text

    def send
      # do things with my_text
    end
  end

  class << self
    def send
      payload = Payload.new
      yield payload
      payload.send
    end
  end

How can I test whether MyModule receives send method with a block, which assigns "payload text" to payload.my_text ?

Currently I'm only testing expect(MyModule).to receive(:send).once . I looked through and tried Rspec yield matchers but cannot get things done. (Maybe I've ben searching for wrong keywords..)

The easiest way is to insert a double as the yield argument, which you can make an assertion on.

payload = Payload.new
allow(Payload).to receive(:new).and_return(payload)

test_target

expect(payload.my_text).to eq 'payload text'

Alternatively you could also use expect_any_instance_of , but I'd always prefer to use a specific double instead.

I would mock MyModule to yield another mock, that would allow speccing that my_text= is called on the yielded object.

let(:payload) { instance_double('Payload') }

before do
  allow(MyModule).to receive(:send).and_yield(payload)
  allow(payload).to receive(:my_text=).and_return(nil)
end

# expectations 
expect(MyModule).to have_received(:send).once
expect(payload).to have_received(:my_text=).with('payload text').once

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM