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.
Image may be NSFW.
Clik here to view.
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.
Image may be NSFW.
Clik here to view.
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