Sorry my example was slightly off (pains of trying to anonymize!), because 
it's actually calling a (now) private method of a different class. Oops!

Here's a better sample:

class Post
  private

  def process # used to be public
    # ...
  end
end

class Operation
  def self.call
    post.process
    # do other things here
  end
end

RSpec.describe Operation do
  subject { described_class }

  it do
    expect(post).to receive(:process)
    subject.call
  end
end

Now the test still succeeds but the code doesn't. I understand your 
suggestion of testing to make sure that methods are the expected 
accessibility, but this is probably too cumbersome in practice in a large 
codebase.

On Tuesday, July 21, 2020 at 4:28:17 PM UTC-4 Jon Rowe wrote:

> Yep that should continue to work, from the perspective of  `call` it 
> doesn’t matter wether `do_something` is private or not, it is just an 
> implementation detail to it.
>
> Really to catch this you should also write a spec for `do_something` in 
> its own right, if its part of your “public api” it is often a good idea to 
> test this.
>
> I wouldn’t advocate this, but if its too expensive to call un-mocked this 
> would check its available publicly:
>
> RSpec.describe “#do_something” do
>   # its too expensive to call in tests, but we want to ensure its public
>   it “is a public method” do
>     object = MyObject.new
>     expect(object).to receive(:do_something)
>     object.do_something
>   end
> end
>
> However, if you’re using standard Ruby semantics, this might make more 
> sense:
>
> RSpec.describe “#do_something” do
>   it “is a public method” do
>     object = MyObject.new
>     expect(object).to respond_to(:do_something)
>   end
> end
>
> Cheers
>
> Jon Rowe
> ---------------------------
> [email protected]
> jonrowe.co.uk
>
> On 21 July 2020 at 21:16, 'Daniel Vandersluis' via rspec wrote:
>
> Jon Rowe,
>
> My test looked something like this:
>
> class MyObject
>   def call
>     do_something
>   end
>
> private
>
>   def do_something # this used to be public!
>     #...
>   end
> end
>
> subject { MyObject.new }
>
> expect(obj).to receive(:do_something)
> subject.call # this calls do_something
>
> Regardless of whether do_something is public or private, the expectation 
> passes, but when called outside of a test, the method fails with 
> NoMethodError because the method became private. I totally agree that the 
> tests we had were not adequate, but also it wasn't something we were able 
> to catch.
>
> Daniel
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"rspec" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/rspec/33f25d23-6c1e-4e01-a650-3a916fb0c2a4n%40googlegroups.com.

Reply via email to