58

In my Rails project I'm using rspec-mocks using any_instance but I want to avoid this deprecation message:

Using any_instance from rspec-mocks' old :should syntax without explicitly enabling the syntax is deprecated. Use the new :expect syntax or explicitly enable :should instead.

Here is my specs:

describe (".create") do
  it 'should return error when...' do
    User.any_instance.stub(:save).and_return(false)
    post :create, user: {name: "foo", surname: "bar"}, format: :json
    expect(response.status).to eq(422)
  end
end

Here is my controller:

def create
    @user = User.create(user_params)
    if @user.save
      render json: @user, status: :created, location: @user
    else
      render json: @user.errors, status: :unprocessable_entity
    end
end

I'd like to use the new :expect syntax but I can't find how to use it properly.

I'm using RSpec 3.0.2.

therealrootuser
  • 10,215
  • 7
  • 31
  • 46
Rowandish
  • 2,655
  • 3
  • 31
  • 52

2 Answers2

115

Use allow_any_instance_of:

describe (".create") do
  it 'returns error when...' do
    allow_any_instance_of(User).to receive(:save).and_return(false)
    post :create, user: {name: "foo", surname: "bar"}, format: :json
    expect(response.status).to eq(422)
  end
end
Uri Agassi
  • 36,848
  • 14
  • 76
  • 93
  • Works perfectly! – Gabriel Mesquita Aug 27 '18 at 18:23
  • And now the `allow_any_instance_of` is also [marked as deprecated](https://relishapp.com/rspec/rspec-mocks/v/3-3/docs/old-syntax/any-instance). Any other solution? – Alexis Wilke Nov 20 '19 at 07:07
  • @AlexisWilke - from what I understand - it is now considered a design smell - you are expected to design your service in such a way that you don't need to stub "any instance", but strive to stub specific instances instead... – Uri Agassi Nov 20 '19 at 13:55
8

I am able to reproduce it :

In my test.rb file :-

#!/usr/bin/env ruby

class Foo
  def baz
    11
  end
end

In my test_spec.rb file

require_relative "../test.rb"

describe Foo do
  it "invokes #baz" do
    Foo.any_instance.stub(:baz).and_return(20)
    expect(subject.baz).to eq(20)
  end
end

Now If I run it :-

arup@linux-wzza:~/Ruby> rspec
.

Deprecation Warnings:

Using `any_instance` from rspec-mocks' old `:should` syntax without explicitly enabling the syntax is deprecated. Use the new `:expect` syntax or explicitly enable `:should` instead. Called from /home/arup/Ruby/spec/test_spec.rb:4:in `block (2 levels) in <top (required)>'.

Now, I found the changelog

allow(Klass.any_instance) and expect(Klass.any_instance) now print a warning. This is usually a mistake, and users usually want allow_any_instance_of or expect_any_instance_of instead. (Sam Phippen)

I change test_spec.rb as below :

require_relative "../test.rb"

describe Foo do
  it "invokes #baz" do
    expect_any_instance_of(Foo).to receive(:baz).and_return(20)
    expect(subject.baz).to eq(20)
  end
end

and it works perfectly :-

arup@linux-wzza:~/Ruby> rspec
.

Finished in 0.01652 seconds (files took 0.74285 seconds to load)
1 example, 0 failures
arup@linux-wzza:~/Ruby>
Arup Rakshit
  • 116,827
  • 30
  • 260
  • 317