Testing Rails model method with rspec

huangapple go评论82阅读模式
英文:

Testing Rails model method with rspec

问题

  1. 我对于为什么这个测试不起作用感到困惑。只有在我给桩方法 `bar` 添加一个返回值时,它才起作用。然而,预期并不希望有一个返回值,所以我只想测试 `foo` 方法内部是否调用了 `bar`
  2. ```ruby
  3. class Event < ApplicationRecord
  4. def foo
  5. bar
  6. end
  7. end

这个测试不起作用。

  1. describe Event, type: :model do
  2. it '调用 bar' do
  3. event = create(:event)
  4. allow(event).to receive(:bar)
  5. expect(event.foo).to receive(:bar)
  6. end
  7. end
  8. 错误信息:
  9. Failure/Error: expect(event.foo).to receive(:bar)
  10. (nil).bar(*(any args))
  11. 期望: 任意参数出现1
  12. 收到: 任意参数未出现

当我修改测试以添加一个返回值时,测试就起作用了。

  1. describe Event, type: :model do
  2. it '调用 bar' do
  3. event = create(:event)
  4. allow(event).to receive(:bar).and_return(true)
  5. expect(event.foo).to eq(true)
  6. end
  7. end
  1. <details>
  2. <summary>英文:</summary>
  3. I&#39;m confused as to why this test isn&#39;t working. It only works when I add a return value to the stubbed `bar` method. However, it is not expected to have a return value, so I only want to test `bar` is called within `foo`.

class Event < ApplicationRecord
def foo
bar
end
end

  1. This test does not work.

describe Event, type: :model do
it 'calls bar' do
event = create(:event)

  1. allow(event).to receive(:bar)
  2. expect(event.foo).to receive(:bar)

end
end

Error message:
Failure/Error: expect(event.foo).to receive(:bar)

(nil).bar(*(any args))
expected: 1 time with any arguments
received: 0 times with any arguments

  1. When I change the test to add a return value the test works.

describe Event, type: :model do
it 'calls bar' do
event = create(:event)

  1. allow(event).to receive(:bar).and_return(true)
  2. expect(event.foo).to eq(true)

end
end

  1. </details>
  2. # 答案1
  3. **得分**: 1
  4. ```plaintext
  5. 在这张图片中有很多问题。
  6. 让我们从方法开始:

class Event < ApplicationRecord
def foo
bar
end
end

  1. 当你调用 `Event.new.foo` 时,你在 `self` 上调用 `#bar`,它是 Event 的实例,而不是方法 `foo`
  2. 如果你做 `expect(event.foo).to receive(:bar)`,你是在方法的返回值上设置期望,这当然不起作用。
  3. 如果你想测试调用 foo 是否会调用 bar,你可以在之前设置期望使用 `expect(obj).to recieve :method_name`
  4. ```lang-ruby
  5. describe Event, type: :model do
  6. it &#39;calls bar&#39; do
  7. event = create(:event)
  8. expect(event).to receive(:bar)
  9. event.foo
  10. end
  11. end

请注意,除非调用了预期的方法,否则示例将失败。

或者,如果你更喜欢安排、行动、断言模式,你可以使用间谍:

  1. describe Event, type: :model do
  2. it &#39;calls bar&#39; do
  3. # 安排
  4. event = create(:event)
  5. allow(event).to receive(:bar)
  6. # 行动
  7. event.foo
  8. # 断言
  9. expect(foo).to have_recieved(:bar)
  10. end
  11. end
  1. <details>
  2. <summary>英文:</summary>
  3. There is a lot of things wrong in this picture.
  4. Lets start with the method:

class Event < ApplicationRecord
def foo
bar
end
end

  1. When you call `Event.new.foo` you&#39;re calling `#bar` on `self` which is the instance of Event. Not on the method `foo`.
  2. If you do `expect(event.foo).to receive(:bar)` you&#39;re setting the expectation on the return value of the method which of course doesn&#39;t work.
  3. If you want to test that calling foo calls bar you can use `expect(obj).to recieve :method_name` if you want to set the expectation before hand:
  4. ````lang-ruby
  5. describe Event, type: :model do
  6. it &#39;calls bar&#39; do
  7. event = create(:event)
  8. expect(event).to receive(:bar)
  9. event.foo
  10. end
  11. end

Note that you don't have to use allow(event).to receive(:bar) unless you want to stub the method. expect(event).to receive(:bar) wraps the method so that RSpec can track the calls to the method.

The example will fail unless the expected method is called.

Or you can use a spy if you prefer the arrage, act, assert pattern:

  1. describe Event, type: :model do
  2. it &#39;calls bar&#39; do
  3. # arrange
  4. event = create(:event)
  5. allow(event).to receive(:bar)
  6. # act
  7. event.foo
  8. # assert
  9. expect(foo).to have_recieved(:bar)
  10. end
  11. end

答案2

得分: -1

  1. 发表问题后找到答案:

describe Event, type: :model do
it '调用 bar' do
event = create(:event)

  1. 允许(event).接收(:bar)
  2. 期望(event).接收(:bar)
  3. event.foo

end
end

英文:

Found the answer after posting my question:

  1. describe Event, type: :model do
  2. it &#39;calls bar&#39; do
  3. event = create(:event)
  4. allow(event).to receive(:bar)
  5. expect(event).to receive(:bar)
  6. event.foo
  7. end
  8. end

huangapple
  • 本文由 发表于 2023年3月1日 16:13:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/75601030.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定