What's the difference between a mock & stub?

Viewed 496704
42 Answers

If you compare it to debugging:

Stub is like making sure a method returns the correct value

Mock is like actually stepping into the method and making sure everything inside is correct before returning the correct value.

let see Test Doubles:

  • Fake: Fakes are objects that have working implementations, but not the same as production one. Such as: in-memory implementation of Data Access Object or Repository.
  • Stub: Stub is an object that holds predefined data and uses it to answer calls during tests. Such as: an object that needs to grab some data from the database to respond to a method call.

  • Mocks: Mocks are objects that register calls they receive. In test assertion, we can verify on Mocks that all expected actions were performed. Such as: a functionality that calls e-mail sending service. for more just check this.

Using a mental model really helped me understand this, rather than all of the explanations and articles, that didn't quite "sink in".

Imagine your kid has a glass plate on the table and he starts playing with it. Now, you're afraid it will break. So, you give him a plastic plate instead. That would be a Mock (same behavior, same interface, "softer" implementation).

Now, say you don't have the plastic replacement, so you explain "If you continue playing with it, it will break!". That's a Stub, you provided a predefined state in advance.

A Dummy would be the fork he didn't even use... and a Spy could be something like providing the same explanation you already used that worked.

Stub

A stub is an object used to fake a method that has pre-programmed behavior. You may want to use this instead of an existing method in order to avoid unwanted side-effects (e.g. a stub could make a fake fetch call that returns a pre-programmed response without actually making a request to a server).

Mock

A mock is an object used to fake a method that has pre-programmed behavior as well as pre-programmed expectations. If these expectations are not met then the mock will cause the test to fail (e.g. a mock could make a fake fetch call that returns a pre-programmed response without actually making a request to a server which would expect e.g. the first argument to be "http://localhost:3008/" otherwise the test would fail.)

Difference

Unlike mocks, stubs do not have pre-programmed expectations that could fail your test.

I was reading The Art of Unit Testing, and stumbled upon the following definition:

A fake is a generic term that can be used to describe either a stub or a mock object (handwritten or otherwise), because they both look like the real object. Whether a fake is a stub or a mock depends on how it's used in the current test. if it's used to check an interaction (asserted against), it's a mock object. Otherwise, it's a stub.

Mocks: help to emulate and examine outcoming interactions. These interactions are calls the SUT makes to its dependencies to change their state.

Stubs: help to emulate incoming interactions. These interactions are calls the SUT makes to its dependencies to get input data.

enter image description here

source : Unit Testing Principles, Practices, and Patterns - Manning

A mock is both a technical and a functional object.

The mock is technical. It is indeed created by a mocking library (EasyMock, JMockit and more recently Mockito are known for these) thanks to byte code generation.
The mock implementation is generated in a way where we could instrument it to return a specific value when a method is invoked but also some other things such as verifying that a mock method was invoked with some specific parameters (strict check) or whatever the parameters (no strict check).

Instantiating a mock :

@Mock Foo fooMock

Recording a behavior :

when(fooMock.hello()).thenReturn("hello you!");

Verifying an invocation :

verify(fooMock).hello()

These are clearly not the natural way to instantiate/override the Foo class/behavior. That's why I refer to a technical aspect.

But the mock is also functional because it is an instance of the class we need to isolate from the SUT. And with recorded behaviors on it, we could use it in the SUT in the same way than we would do with a stub.


The stub is just a functional object : that is an instance of the class we need to isolate from the SUT and that's all. That means that both the stub class and all behaviors fixtures needed during our unit tests have to be defined explicitly.
For example to stub hello() would need to subclass the Foo class (or implements its interface it has it) and to override hello() :

public class HelloStub extends Hello{    
  public String hello { 
      return "hello you!"; 
  }
}

If another test scenario requires another value return, we would probably need to define a generic way to set the return :

public class HelloStub extends Hello{    
  public HelloStub(String helloReturn){
       this.helloReturn = helloReturn;
  }
  public String hello { 
      return helloReturn; 
  }
}

Other scenario : if I had a side effect method (no return) and I would check that that method was invoked, I should probably have added a boolean or a counter in the stub class to count how many times the method was invoked.


Conclusion

The stub requires often much overhead/code to write for your unit test. What mock prevents thanks to providing recording/verifying features out of the box.
That's why nowadays, the stub approach is rarely used in practice with the advent of excellent mock libraries.


About the Martin Fowler Article : I don't think to be a "mockist" programmer while I use mocks and I avoid stubs.
But I use mock when it is really required (annoying dependencies) and I favor test slicing and mini-integration tests when I test a class with dependencies which mocking would be an overhead.

Plus useful answers, One of the most powerful point of using Mocks than Subs

If the collaborator [which the main code depend on it] is not under our control (e.g. from a third-party library),
In this case, stub is more difficult to write rather than mock.

Stub helps us to run test. How? It gives values which helps to run test. These values are itself not real and we created these values just to run the test. For example we create a HashMap to give us values which are similar to values in database table. So instead of directly interacting with database we interact with Hashmap.

Mock is an fake object which runs the test. where we put assert.

A stub is a test double that returns values to the SUT.

A mock is a test double that a test uses to verify that the SUT correctly invokes a dependency.

Also, a mock is often a stub

Stub

A stub is an object that holds predefined data and uses it to answer calls during tests. It is used when you can’t or don’t want to involve objects that would answer with real data or have undesirable side effects.

An example can be an object that needs to grab some data from the database to respond to a method call. Instead of the real object, we introduced a stub and defined what data should be returned.

enter image description here


example of Stub:

public class GradesService {

   private final Gradebook gradebook;

   public GradesService(Gradebook gradebook) {
       this.gradebook = gradebook;
   }

   Double averageGrades(Student student) {
       return average(gradebook.gradesFor(student));
   }
}

Instead of calling database from Gradebook store to get real students grades, you preconfigure stub with grades that will be returned. You define just enough data to test average calculation algorithm.

public class GradesServiceTest {

   private Student student;
   private Gradebook gradebook;

   @Before
   public void setUp() throws Exception {
       gradebook = mock(Gradebook.class);
       student = new Student();
   }

   @Test
   public void calculates_grades_average_for_student() {
       //stubbing gradebook
       when(gradebook.gradesFor(student)).thenReturn(grades(8, 6, 10)); 

       double averageGrades = new GradesService(gradebook).averageGrades(student);

       assertThat(averageGrades).isEqualTo(8.0);
   }
}


Mock

Mocks are objects that register calls they receive. In test assertion you can verify on Mocks that all expected actions were performed. You use mocks when you don’t want to invoke production code or when there is no easy way to verify, that intended code was executed. There is no return value and no easy way to check system state change. An example can be a functionality that calls e-mail sending service.

You don’t want to send e-mails each time you run a test. Moreover, it is not easy to verify in tests that a right email was send. Only thing you can do is to verify the outputs of the functionality that is exercised in our test. In other worlds, verify that the e-mail sending service was called.

enter image description here


Example of Mock:

public class SecurityCentral {

   private final Window window;
   private final Door door;

   public SecurityCentral(Window window, Door door) {
       this.window = window;
       this.door = door;
   }

   void securityOn() {
       window.close();
       door.close();
   }
}

You don’t want to close real doors to test that security method is working, right? Instead, you place door and window mocks objects in the test code.

public class SecurityCentralTest {

   Window windowMock = mock(Window.class);
   Door doorMock = mock(Door.class);

   @Test
   public void enabling_security_locks_windows_and_doors() {
       SecurityCentral securityCentral = new SecurityCentral(windowMock, doorMock);

       securityCentral.securityOn();

       verify(doorMock).close();
       verify(windowMock).close();
   }
}

Thanks a lot to Michał Lipski for his good article. For further reading:

Test Double – Martin Fowler https://martinfowler.com/bliki/TestDouble.html
Test Double – xUnit Patterns http://xunitpatterns.com/Test%20Double.html
Mocks Aren’t Stubs – Martin Fowler https://martinfowler.com/articles/mocksArentStubs.html
Command Query Separation – Martin Fowler https://martinfowler.com/bliki/CommandQuerySeparation.html

Say you have a class named EmployeeService that you want to test and that has one dependency on an interface named EmployeeDao:

public class EmployeeService{
   private EmployeeDao dao;
   public EmployeeService(Dao dao){this.dao = dao;}

   public String getEmployeeName(int id){
     Employee emp = bar.goToDatabaseAndBringTheEmployeeWithId(id);
     return emp != null?emp.getFullName:null;
   }
   //Further state and behavior
}

public interface EmployeeDao{
  Employee goToDatabaseAndBringTheEmployeeWithId(int id);
}

Inside your test class:

public class EmployeeServiceTest{
   EmployeeService service;
   EmployeeDao mockDao = Mockito.mock(EmployeeDao.class);//Line 3

   @Before
   public void setUp(){
     service = new EmployeeService(mockDao);
   }
   //Tests
   //....
}

In the above test class in line 3, we say to the mocking framework (in this case Mockito) "Hey, Mockito, craft me an object that has the EmployeeDao functionality." The framework is going to create an object that has the method goToDatabaseAndBringTheEmployeeWithId but actually with no body. It's your job to instruct that mock what to do. This is a mock.

But you could also create a class that implements the EmployeeDao interface and use it in the test class instead:

public EmployeeDaoStub implements EmployeeDao{
   public Employee goToDatabaseAndBringTheEmployeeWithId(int id){
      //No trip to DB, just returning a dummy Employee object
      return new Employee("John","Woo","123 Lincoln str");
   }
}

Inside your test class this time using stub instead of a mock:

public class EmployeeServiceTest{
   EmployeeService service;
   EmployeeDao daoStub = new EmployeeDaoStub();//Line 3

   @Before
   public void setUp(){
     service = new EmployeeService(daoStub);
   }
   //Tests
   //....
}

So to wrap it all, stubs are the classes that you create(or somebody else does) specifically to imitate some dependency just for the sake of having the desired state. Yes, as all the other people state, it's mostly about a state Whereas mocks are typically created by a mocking framework and you have no idea what its guts look like. But with stubs you know what class you're going to get: It's the one you created.

Oh, btw, if your dependency is a class rather than an interface, you can just extend that class to create your stub.

Both Stubs and Mocks override external dependencies but the difference is

Stubs -> To Test Data

Mocks -> To Test Behavior


Fake/Dummy -> Test nothing (just override functionality with empty methods, eg replace Logger to avoid any logging noise while testing)

A test subject performs actions in response to certain prompts (function calls) or other stimuli. Here are concrete examples of test situations.

Scenario -- EMT student exam

A student has studied to be an Emergency Medical Technician. Go watch Ian Gallagher in Shameless Season 6, Episode 10 if you are unfamiliar with this test situation.

It is too expensive to find patients with various illnesses for test purposes. Instead we use actors. We ask the test subject (Ian) "you arrive on the scene and the patient is immobilized and unconscious what do you do first?" Ian responds "I check if the scene is safe". And the test instructor says "the scene is safe".

The instructor (and actor) are able to inject arbitrary answers to the test subject's queries.

Here, the instructor (and actor) are a mock. Medical training uses this terminology (e.g. mock code simulation) the same as computer scientists.

Scenario -- register for a website

You are testing Yahoo, a new email service you heard about. In order to sign up, you must provide your birthday and answers to other intrusive questions.

The website requires that you are 21 years or older. So you enter in the value January 1, 1970. It meets the requirements and it saves you from the laborious process of implementing a remember-my-birthday-and-type-it-in workflow.

This date is a stub. This word usage is specific to computer science.

There a lots of greats answers, and I liked this one, so I turned it into a table.

Dummy Stub Mock Fake
API O O O O
States X O O O
Values X X O O
Behavior X X X O
Related