You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Generic functions are supported, but require some care to use, as they get treated a little differently from other functionality.
94
95
95
-
Given a function:
96
+
Spyable supports generic functions, but their implementation involves special handling. Due to limitations in Swift, generic parameters in a function are replaced with `Any` in the spy class to store arguments, return values, and closures.
97
+
98
+
For example:
96
99
97
100
```swift
98
101
funcfoo<T, U>(_bar: T) -> U
99
102
```
100
103
101
-
The following will be created in a spy:
104
+
Generates the following spy:
102
105
103
106
```swift
104
107
classMyProtocolSpy: MyProtocol {
105
108
var fooCallsCount =0
106
109
var fooCalled: Bool {
107
-
return fooCallsCount >0
110
+
return fooCallsCount >0
108
111
}
109
112
var fooReceivedBar: Any?
110
113
var fooReceivedInvocations: [Any] = []
111
114
var fooReturnValue: Any!
112
115
var fooClosure: ((Any) ->Any)?
116
+
113
117
funcfoo<T, U>(_bar: T) -> U {
114
118
fooCallsCount +=1
115
119
fooReceivedBar = (bar)
@@ -122,12 +126,13 @@ class MyProtocolSpy: MyProtocol {
122
126
}
123
127
}
124
128
```
125
-
Uses of `T` and `U` get substituted with `Any` because generics specified only by a function can't be stored as a property in the function's class. Using `Any` lets us store injected closures, invocations, etc.
126
129
127
-
Force casts get used to turn an injected closure or returnValue property from `Any` into an expected type. This means that *it's essential that expected types match up with values given to these injected properties*.
130
+
#### Important Notes:
128
131
129
-
##### Example:
130
-
Given the following code:
132
+
1.**Type Matching**:
133
+
Ensure the expected types align with the injected `returnValue` or `closure`. Mismatched types will result in runtime crashes due to force casting.
134
+
135
+
2.**Example**:
131
136
132
137
```swift
133
138
@Spyable
@@ -144,24 +149,21 @@ struct ViewModel {
144
149
}
145
150
```
146
151
147
-
A test for ViewModel's `wrapData()` function could look like this:
152
+
Test for `wrapData()`:
148
153
149
154
```swift
150
155
functestWrapData() {
151
-
// Important: When using generics, mocked return value types must match the types that are being returned in the use of the spy.
//⚠️ The following would be incorrect, and cause a fatal error, because an Array<String> will be returned by wrapData(), but here we'd be providing an Array<Int> to wrapDataInArrayReturnValue. ⚠️
0 commit comments