Skip to content
This repository was archived by the owner on Oct 2, 2025. It is now read-only.

Commit 81f58ae

Browse files
author
Felix Jendrusch
committed
Update README.md
1 parent 3e65704 commit 81f58ae

File tree

1 file changed

+82
-9
lines changed

1 file changed

+82
-9
lines changed

README.md

Lines changed: 82 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
# Dobby
22

3-
Dobby provides a few helpers for mocking and stubbing using expectations.
3+
Dobby provides a few helpers for mocking and stubbing.
44

5-
## Expectations
5+
## Matchers
66

7-
Expectations can be matched with values, serving as the fundamental building block for mocking and stubbing. There are many functions that help creating expectations for (equatable) types, including tuples, arrays, and dictionaries with equatable elements:
7+
Matchers can be matched with values, serving as the fundamental building block for mocking and stubbing. There are many functions that help creating matchers for (equatable) types, including optionals, tuples, arrays, and dictionaries with equatable elements:
88

99
```swift
1010
matches { $0 == value } // matches value
1111
any() // matches anything
12+
not(0) // matches anything but 0
13+
none() // matches Optional<T>.None (nil)
14+
some(1) // matches Optional<T>.Some(1)
1215
equals(1) // matches 1
1316
equals((1, 2)) // matches (1, 2)
1417
equals((1, 2, 3)) // matches (1, 2, 3)
@@ -18,28 +21,98 @@ equals([1, 2, 3]) // matches [1, 2, 3]
1821
equals([1: 1, 2: 2, 3: 3]) // matches [1: 1, 2: 2, 3: 3]
1922
```
2023

21-
Expectations may also be nested:
24+
Matchers may also be nested:
2225

2326
```swift
2427
matches((matches { $0 == 0 }, any(), 2)) // matches (0, _, 2)
28+
matches((not(equals(3)), some(any()))) // matches (not(3), _)
2529
matches([any(), equals(4)]) // matches [_, 4]
2630
matches(["key": matches { $0 == 5 }]) // matches ["key": 5]
2731
```
2832

2933
## Mocks
3034

31-
Mocks can be used to verify that all set up expectations are matched with the recorded interactions. Verification is performed in order and all expectations must match an interaction and vice versa:
35+
Mocks can be used to verify that all set up expectations have been fulfilled.
36+
37+
### Strict mocks
38+
39+
By default, mocks are strict and the order of expectations matters, meaning all interactions must be expected and occur in the order they were expected:
3240

3341
```swift
3442
let mock = Mock<[Int]>()
3543
mock.expect(matches([any(), matches { $0 > 0 }])) // expects [_, n > 0]
36-
mock.record([0, 1])
44+
mock.record([0, 1]) // succeeds
45+
mock.verify() // succeeds
46+
mock.record([1, 0]) // fails (fast)
47+
```
48+
49+
The order of expectations may also be ignored:
50+
51+
```swift
52+
let mock = Mock<[String: Int]>(ordered: false)
53+
mock.expect(matches([0, 1]))
54+
mock.expect(matches([1, 0]))
55+
mock.record([1, 0]) // succeeds
56+
mock.record([0, 1]) // succeeds
57+
mock.verify() // succeeds
58+
mock.record([0, 0]) // fails (fast)
59+
```
60+
61+
### Nice mocks
62+
63+
Nice mocks allow unexpected interactions while still respecting the order of expectations:
64+
65+
```swift
66+
let mock = Mock<[Int?]>(strict: false)
67+
mock.expect(matches([some(0)]))
68+
mock.expect(matches([some(any())]))
69+
mock.record([nil]) // succeeds
70+
mock.verify() // fails
71+
mock.record([1]) // fails (fast)
72+
mock.record([0]) // succeeds
73+
mock.record([1]) // succeeds
3774
mock.verify() // succeeds
3875
```
3976

77+
Of course, nice mocks can ignore the order of expectations too:
78+
79+
```swift
80+
let mock = Mock<[String: Int?]>(strict: false, ordered: false)
81+
mock.expect(matches(["zero": some(0)]))
82+
mock.expect(matches(["none": none()]))
83+
mock.record(["none": nil]) // succeeds
84+
mock.record(["zero": 0]) // succeeds
85+
mock.verify() // succeeds
86+
```
87+
88+
#### Negative expectations
89+
90+
In addition to normal expectations, nice mocks allow negative expectations to be set up:
91+
92+
```swift
93+
let mock = Mock<Int>(strict: false)
94+
mock.reject(0)
95+
mock.record(0) // fails (fast)
96+
```
97+
98+
### Verification with delay
99+
100+
Verification may also be performed with a delay, allowing expectations to be fulfilled asynchronously:
101+
102+
```swift
103+
let mock = Mock<Int>()
104+
mock.expect(1)
105+
106+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1.0 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
107+
mock.record(1) // succeeds
108+
}
109+
110+
mock.verifyWithDelay(2.0) // succeeds
111+
```
112+
40113
## Stubs
41114

42-
Stubs, when invoked, return a value based on their set up behavior, or, if an interaction is unexpected, return `nil`. Behavior is matched in order, i.e., the function or return value associated with the first expectation that matches an interaction is invoked/returned:
115+
Stubs, when invoked, return a value based on their set up behavior, or, if an interaction is unexpected, return `nil`. Behavior is matched in order, i.e., the function or return value associated with the first matcher that matches an interaction is invoked/returned:
43116

44117
```swift
45118
let stub = Stub<(Int, Int), Int>()
@@ -75,14 +148,14 @@ class MyClassMock: MyClass {
75148
let myMethodMock = Mock<(String, String)>()
76149
let myMethodStub = Stub<(String, String), String>()
77150
override func myMethod(fst: String, _ snd: String) -> String {
78-
myMethodMock.record(fst, snd)
151+
myMethodMock.record((fst, snd))
79152
// Call super if the stub doesn't define any behavior for the interaction.
80153
return myMethodStub.invoke(fst, snd) ?? super.myMethod(fst, snd)
81154
}
82155
}
83156
```
84157

85-
The test subclass allows you to verify that all your set up expectations are matched with the recorded interactions and enables you to change its behavior on-the-fly:
158+
The test subclass allows you to verify that all your set up expectations are fulfilled and enables you to change its behavior on-the-fly:
86159

87160
```swift
88161
let myClassMock = MyClassMock()

0 commit comments

Comments
 (0)