What's the difference between mock, stub, and factory girl?
Asked Answered
D

2

32

I'm pretty new to rspec and the whole TDD methodology. Can someone please explain the difference between mock and stub. When do we use them and when do we use Factory Girl to create objects in test cases?

Damascene answered 7/9, 2011 at 21:38 Comment(0)
R
17

You could think of a mock (or double) as a fake object. When you're testing and need to work with an object that isn't easily usable inside your test, you could use a mock as an approximation for how you expect that object to behave and work around it. Stubs can be used in a similar manner but on an individual method on an object.

Here's a rather contrived example of using a lot of both:

class Client
  def connect_to_server
    if Server.connect.status == 'bad'
      show_an_error
    else
      do_something_else
    end
  end
  def do_something_else; end
  def show_an_error; end
end

context "failure" do
  it "displays an error" do
    bad_network_response = double("A bad response from some service", :status => 'bad')
    Server.should_receive(:connect).and_return(bad_network_response)

    client = Client.new
    client.should_receive(:show_an_error)
    client.connect_to_server
  end
end

You can imagine that using a lot of mocks or stubbing is a bad idea; this is basically masking out parts of your code in your test but, it's an easy solution for some difficult/rare testing scenarios.

Factory Girl is useful for generating data for tests. You would use factories as recipes for creating instances for your models, you might need to test something involving a lot of test data and this would be a situation where using fixtures won't work and creating complicated objects explicitly can be tedious.

Riva answered 7/9, 2011 at 23:2 Comment(1)
I could be wrong, but I think you are mistaken on stubs just being on methods. You could have stub objects or mock objects, or stubbed methods or mocked methods. The difference is how you are using them. Stubs are to just get the test working without actually invoking another dependency. Mocks do the same but the invocation is required and part of the test. You could have a fake object that has both stubs and mocks. Rspec even calls them "double" now instead of mock.Rothermere
T
18

Your first stop is Martin Fowler's famous article : Mocks are not Stubs

Edit

Mocks and Stubs are two of the types of Test Doubles (Mezaros terminology). Test doubles are typically used to simulate the dependencies needed by a System Under Test (or Class Under Test), so that the SUT / CUT may be tested in isolation from its dependencies. (Caveat - precise terminology can be quite a touchy subject e.g. as mentioned by Jeff here)

From wikipedia:

Examples

  • A stub method may just return a constant value when called by the SUT, e.g. for conducting a specific test case of the SUT.
  • *Frameworks like Mockito (Java) and Moq (.Net) allow you to build mock classes against a dependency's interface on the fly with a minimum of code, and provide the ability to verify that the SUT interacted correctly with the mock, e.g. by checking that the SUT invoked the mock's methods the correct number of times, with the correct parameters.

* Disclaimer - I'm not a ruby dev

Theatricalize answered 7/9, 2011 at 21:41 Comment(1)
When you've read that, you can move onto Making a Mockery of TDDJaved
R
17

You could think of a mock (or double) as a fake object. When you're testing and need to work with an object that isn't easily usable inside your test, you could use a mock as an approximation for how you expect that object to behave and work around it. Stubs can be used in a similar manner but on an individual method on an object.

Here's a rather contrived example of using a lot of both:

class Client
  def connect_to_server
    if Server.connect.status == 'bad'
      show_an_error
    else
      do_something_else
    end
  end
  def do_something_else; end
  def show_an_error; end
end

context "failure" do
  it "displays an error" do
    bad_network_response = double("A bad response from some service", :status => 'bad')
    Server.should_receive(:connect).and_return(bad_network_response)

    client = Client.new
    client.should_receive(:show_an_error)
    client.connect_to_server
  end
end

You can imagine that using a lot of mocks or stubbing is a bad idea; this is basically masking out parts of your code in your test but, it's an easy solution for some difficult/rare testing scenarios.

Factory Girl is useful for generating data for tests. You would use factories as recipes for creating instances for your models, you might need to test something involving a lot of test data and this would be a situation where using fixtures won't work and creating complicated objects explicitly can be tedious.

Riva answered 7/9, 2011 at 23:2 Comment(1)
I could be wrong, but I think you are mistaken on stubs just being on methods. You could have stub objects or mock objects, or stubbed methods or mocked methods. The difference is how you are using them. Stubs are to just get the test working without actually invoking another dependency. Mocks do the same but the invocation is required and part of the test. You could have a fake object that has both stubs and mocks. Rspec even calls them "double" now instead of mock.Rothermere

© 2022 - 2024 — McMap. All rights reserved.