1
votes

Why would you use stub given that you should be testing real classes anyways?

I know there are cases that you don't want to test other classes and not go through its other associated class methods but I still think it's better to use real methods.

I can only really see a benefit when you want to quickly skip one method's other associated tasks and return the end result to be used in tests

Are there other benefits though that we should be considering?

(In addition to above I also think stub is risky aswell since your code can change as it evolves and may generate different output to what it is generating in the tests)

1
The bottleneck to using stubs is as simple as stubbing the wrong thing. They're awesome in helping to avoid hitting a database, or avoid touching associated data that might not be generated. If you're unit testing, stubs are usually a great tool. Unit tests should be simple, they shouldn't need to test all the associated data or the process of applying that data. Stubbing the right thing is what people usually get wrong.Lee Jarvis
In a serious large enterprise application where any little change is extremely sensitive, wouldn't it be better to avoid stub and rather actually test out with database interaction aswell? (with test database and test data)Passionate Engineer

1 Answers

1
votes

It depends on the test that you are performing. For unit tests, where you are only testing a single class, stubs are beneficial.

As an example, assume you are testing a class which sends an email when some other object finishes the did_it! operation:

describe Emailer do
  context ".send_email" do
    it "sends an email if another object 'did_it!'" do
      obj = Obj.new
      Emailer.send_email(obj).should == true # the email sends successfully
    end
  end
end

In this case, if obj.did_it! is a super expensive operation, or it could fail intermittently, this test could have issues.

However, in this test we only care that Emailer.send_email runs correctly when obj.did_it! returns true--we do not care that the obj.did_it! method works, because that is not what we are testing.

So, we use stubs to say, "assuming that obj.did_it! succeeds, does Emailer.send_email actually send email?":

describe Emailer do
  context ".send_email" do
    it "sends an email if another object 'did_it!'" do
      obj = stub(:did_it! => true)
      Emailer.send_email(obj).should == true # the email sends successfully
    end
  end
end