Test doubles (mocks, stubs) in Swift - Time & Space Complexity
When using test doubles like mocks and stubs, it's important to understand how their use affects the time your tests take to run.
We want to see how the test execution time grows as the number of test doubles or interactions increases.
Analyze the time complexity of the following Swift test code using mocks and stubs.
class ServiceMock {
var callCount = 0
func fetchData() -> String {
callCount += 1
return "mock data"
}
}
func testService(n: Int) {
let mock = ServiceMock()
for _ in 0..
This code simulates calling a mocked service method multiple times in a test.
- Primary operation: Calling
fetchData()on the mock object. - How many times: Exactly
ntimes, controlled by the loop.
Each call to the mock method happens once per loop iteration, so total calls grow directly with n.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 calls to fetchData() |
| 100 | 100 calls to fetchData() |
| 1000 | 1000 calls to fetchData() |
Pattern observation: The number of operations grows in a straight line as n increases.
Time Complexity: O(n)
This means the test time grows directly in proportion to how many times the mock method is called.
[X] Wrong: "Using mocks makes tests run instantly, no matter how many calls happen."
[OK] Correct: Each call to a mock method still takes time, so more calls mean longer test runs.
Understanding how test doubles affect test speed helps you write efficient tests and shows you think about code quality beyond just correctness.
What if the mock method itself called another mock inside it? How would that affect the time complexity?
Practice
mock in Swift testing?Solution
Step 1: Understand what a mock does
A mock is a test double that records how it was used, such as which methods were called and with what arguments.Step 2: Compare with other test doubles
Unlike stubs, mocks focus on interaction verification, not just providing fixed answers.Final Answer:
To record how a function was called during a test -> Option AQuick Check:
Mock = Records calls [OK]
- Confusing mocks with stubs
- Thinking mocks speed up production
- Believing mocks replace the whole app
Solution
Step 1: Check method signature and return type
The method must return an Int, so the signature should befunc getNumber() -> Int.Step 2: Verify the return statement
The method should return the integer 42, soreturn 42is correct.Final Answer:
func getNumber() -> Int { return 42 } -> Option AQuick Check:
Stub returns fixed value [OK]
- Missing return type in function signature
- Returning wrong data type
- Using print instead of return
class ServiceMock {
var fetchCalled = false
func fetchData() {
fetchCalled = true
}
}
let mock = ServiceMock()
mock.fetchData()
print(mock.fetchCalled)
What will be printed?Solution
Step 1: Understand the mock class behavior
The class has a boolean propertyfetchCalledinitially false. The methodfetchData()sets it to true.Step 2: Trace the code execution
After creatingmock, callingmock.fetchData()setsfetchCalledto true. Printing it outputs true.Final Answer:
true -> Option BQuick Check:
Mock records call = true [OK]
- Assuming fetchCalled stays false
- Expecting nil instead of Bool
- Thinking code won't compile
class DataStub {
func getData() -> String {
print("Fixed data")
}
}
What is the error and how to fix it?Solution
Step 1: Identify the method signature and body
The method declares it returns a String but only callsprintwithout returning anything.Step 2: Fix the missing return
Replaceprint("Fixed data")withreturn "Fixed data"to satisfy the return type.Final Answer:
Missing return statement; addreturn "Fixed data"-> Option DQuick Check:
Stub must return value, not print [OK]
- Confusing print with return
- Changing method name unnecessarily
- Changing return type incorrectly
Downloader that calls a network service. To avoid real network calls, you create a mock service that records if download() was called and a stub that returns fixed data. Which approach correctly combines mocks and stubs for this test?Solution
Step 1: Understand roles of mocks and stubs
Mocks record interactions like method calls; stubs provide fixed return data.Step 2: Apply correct combination
Use a mock to check ifdownload()was called, and a stub to supply fixed data forfetchData()to avoid real network calls.Final Answer:
Use a mock to recorddownload()calls and a stub to return fixed data whenfetchData()is called -> Option CQuick Check:
Mock records calls + Stub returns data [OK]
- Using only one test double type
- Relying on real network in tests
- Confusing mock and stub roles
Ready to prove it?
Pass the test and this pattern moves unknown
