Don’t Fear The Test: A Beginner Guide to Mock and Stub
Honestly, I never know mock and stub until I find myself that I can’t test a certain method on my project. Yes, mock and stub are related to test. In this article, I want to enlighten you guys about mock and stub in our beloved programming language, swift.
Stubbing in Swift
Martin Fowler wrote an excellent article on this subject. Quoted from the article:
Meszaros uses the term Test Double as the generic term for any kind of pretend object used in place of a real object for testing purposes. The name comes from the notion of a Stunt Double in movies. (One of his aims was to avoid using any name that was already widely used.) Meszaros then defined four particular kinds of double:
Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).
Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what’s programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it ‘sent’, or maybe only how many messages it ‘sent’.
Mocks are what we are talking about here: objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
To put it in my own words: mock objects is hard-coded JSON results that mimic what would be returned from the webserver. That’s all. Assuming you have a FoodClient
that fetches a Food
, the stub may look like this:
As you can see, the fetchFood
method in our stub just returns the same food which is Donut with a quantity of 2. Our stub didn’t need to wait for API call which is async and slow. For unit test, it’s better to avoid calling the actual implementation of API call. Our
Now, let’s say we have a BlogViewModel
that uses a BlogClient
to fetch a Blog
and we want to test it. If the fetch
is asynchronous and slow, you’d want to avoid calling the actual implementation in your unit tests. So you might test it with a stub like this:
Here we’re just creating an instance of our FoodClientStub
and passing it to our FoodViewModel
. Well, for you guys who doesn't have any idea about what ViewModel is, I recommend you to visit my previous article about MVVM. In this case, we can always expect that the FoodViewModel will always return the same thing.
That’s all about stubs. So simple and straightforward right? Okay lets get to the next little thing called mock.
Mocking in Swift
From Wikipedia, mock objects are simulated objects that mimic the behaviour of real objects in controlled ways, most often as part of a software testing initiative.
I don’t know about you guys but in my eyes, mocking and stub seems like the same thing right? Well, there may be some different opinion of this one but in my opinion, a stub is like a minimal version of a mock.
The example of mock is here, assuming that our fetchFood() will return doughnut on Monday, pretzel on Tuesday and Friday, and return nothing when it’s Sunday:
We can see that our mock need to verify the behaviour of our method. A mock is like a stub but the test will also verify that the object under test calls the mock as expected. in our test_food_name(), we already expected every possible outcome of our fetchFood(). In a real case, its usually an API call function that we mocked. Essentially, a mock is a stub object that also includes the expectations (i.e. “assertions”) for proper behaviour of the object/method under test.
In stub example above, whatever day it is, it will always return doughnut as Food object. In contrast, our mock object responds to our day parameter and return food in response to the day. That’s what makes stub more simple than mock.
Why Mock/Stub?
In unit testing, we want to test methods of one method in isolation. But the problem is, not every method is isolated. They are using services and methods from other classes. So in that case, we mock the services and methods from other classes and simulate the real behaviour using some technique called mock and stub.
Also, in TDD, the speed of testing is so crucial. If we are testing a big app with a whole lot of services, then we need to wait for the services to give their responses, assuming that the services always work as expected. That’s why it’s very important to mock/stub.
That’s all folks! I hope you enjoy my little article. Those examples above about mock and stub is actually the simplest example I could think of and maybe can’t work in some real problem. I encourage you to find another reference for mock and stub in your very language.
Adios!!