Testing Rails model method with rspec

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

Testing Rails model method with rspec

问题

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

这个测试不起作用。

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

    expect(event.foo).to receive(:bar)
  end
end


错误信息:
Failure/Error: expect(event.foo).to receive(:bar)
     
  (nil).bar(*(any args))
     期望: 任意参数出现1
     收到: 任意参数未出现

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

describe Event, type: :model do
  it '调用 bar' do
    event = create(:event)
    
    allow(event).to receive(:bar).and_return(true)

    expect(event.foo).to eq(true)
  end
end

<details>
<summary>英文:</summary>

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


This test does not work. 

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

allow(event).to receive(:bar)

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



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)

allow(event).to receive(:bar).and_return(true)

expect(event.foo).to eq(true)

end
end





</details>


# 答案1
**得分**: 1

```plaintext
在这张图片中有很多问题。

让我们从方法开始:

class Event < ApplicationRecord
def foo
bar
end
end


当你调用 `Event.new.foo` 时,你在 `self` 上调用 `#bar`,它是 Event 的实例,而不是方法 `foo`。

如果你做 `expect(event.foo).to receive(:bar)`,你是在方法的返回值上设置期望,这当然不起作用。

如果你想测试调用 foo 是否会调用 bar,你可以在之前设置期望使用 `expect(obj).to recieve :method_name`:

```lang-ruby
describe Event, type: :model do
  it &#39;calls bar&#39; do
    event = create(:event)
    expect(event).to receive(:bar)
    event.foo
  end
end

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

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

describe Event, type: :model do
  it &#39;calls bar&#39; do
    # 安排
    event = create(:event) 
    allow(event).to receive(:bar) 
    # 行动
    event.foo
    # 断言
    expect(foo).to have_recieved(:bar)
  end
end

<details>
<summary>英文:</summary>

There is a lot of things wrong in this picture. 

Lets start with the method:

class Event < ApplicationRecord
def foo
bar
end
end


When you call `Event.new.foo` you&#39;re calling `#bar` on `self` which is the instance of Event. Not on the method `foo`. 

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.

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:

````lang-ruby
describe Event, type: :model do
  it &#39;calls bar&#39; do
    event = create(:event)
    expect(event).to receive(:bar)
    event.foo
  end
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:

describe Event, type: :model do
  it &#39;calls bar&#39; do
    # arrange
    event = create(:event) 
    allow(event).to receive(:bar) 
    # act
    event.foo
    # assert
    expect(foo).to have_recieved(:bar)
  end
end

答案2

得分: -1

发表问题后找到答案:

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

允许(event).接收(:bar)

期望(event).接收(:bar)

event.foo

end
end

英文:

Found the answer after posting my question:

describe Event, type: :model do
  it &#39;calls bar&#39; do
    event = create(:event)
    
    allow(event).to receive(:bar)

    expect(event).to receive(:bar)

    event.foo
  end
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:

确定