Skip to content

Commit 2128c42

Browse files
authored
Add XCTest extensions (#57)
* Added expectations for on request and completion * Updated the readme
1 parent 89a2234 commit 2128c42

File tree

7 files changed

+102
-18
lines changed

7 files changed

+102
-18
lines changed

Mocker.xcodeproj/project.pbxproj

+12
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
501B8FC4247E89C600B885F4 /* XCTest+Mocker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 501B8FC3247E89C600B885F4 /* XCTest+Mocker.swift */; };
1011
501E269E1F3DAE370048F39E /* Mocker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 501E26941F3DAE370048F39E /* Mocker.framework */; };
1112
503446171F3DB4660039D5E4 /* Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 503446141F3DB4660039D5E4 /* Mock.swift */; };
1213
503446181F3DB4660039D5E4 /* Mocker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 503446151F3DB4660039D5E4 /* Mocker.swift */; };
@@ -28,6 +29,8 @@
2829
/* End PBXContainerItemProxy section */
2930

3031
/* Begin PBXFileReference section */
32+
501B8FC3247E89C600B885F4 /* XCTest+Mocker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCTest+Mocker.swift"; sourceTree = "<group>"; };
33+
501B8FC5247E8BDE00B885F4 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
3134
501E26941F3DAE370048F39E /* Mocker.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Mocker.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3235
501E269D1F3DAE370048F39E /* MockerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MockerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3336
501F8B2D237594AC008EF77E /* Mocker.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = Mocker.podspec; sourceTree = "<group>"; };
@@ -65,6 +68,7 @@
6568
501E268A1F3DAE370048F39E = {
6669
isa = PBXGroup;
6770
children = (
71+
501B8FC5247E8BDE00B885F4 /* README.md */,
6872
506277CC235F2777000A4316 /* Changelog.md */,
6973
501F8B2D237594AC008EF77E /* Mocker.podspec */,
7074
501E26951F3DAE370048F39E /* Products */,
@@ -89,6 +93,7 @@
8993
503446141F3DB4660039D5E4 /* Mock.swift */,
9094
503446151F3DB4660039D5E4 /* Mocker.swift */,
9195
503446161F3DB4660039D5E4 /* MockingURLProtocol.swift */,
96+
501B8FC3247E89C600B885F4 /* XCTest+Mocker.swift */,
9297
);
9398
path = Sources;
9499
sourceTree = "<group>";
@@ -264,6 +269,7 @@
264269
buildActionMask = 2147483647;
265270
files = (
266271
503446191F3DB4660039D5E4 /* MockingURLProtocol.swift in Sources */,
272+
501B8FC4247E89C600B885F4 /* XCTest+Mocker.swift in Sources */,
267273
503446181F3DB4660039D5E4 /* Mocker.swift in Sources */,
268274
503446171F3DB4660039D5E4 /* Mock.swift in Sources */,
269275
);
@@ -419,6 +425,9 @@
419425
DYLIB_COMPATIBILITY_VERSION = 1;
420426
DYLIB_CURRENT_VERSION = 1;
421427
DYLIB_INSTALL_NAME_BASE = "@rpath";
428+
FRAMEWORK_SEARCH_PATHS = (
429+
"$(PLATFORM_DIR)/Developer/Library/Frameworks\n$(PLATFORM_DIR)/Developer/Library/Frameworks",
430+
);
422431
INFOPLIST_FILE = "Mocker/Supporting Files/Info.plist";
423432
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
424433
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
@@ -439,6 +448,9 @@
439448
DYLIB_COMPATIBILITY_VERSION = 1;
440449
DYLIB_CURRENT_VERSION = 1;
441450
DYLIB_INSTALL_NAME_BASE = "@rpath";
451+
FRAMEWORK_SEARCH_PATHS = (
452+
"$(PLATFORM_DIR)/Developer/Library/Frameworks\n$(PLATFORM_DIR)/Developer/Library/Frameworks",
453+
);
442454
INFOPLIST_FILE = "Mocker/Supporting Files/Info.plist";
443455
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
444456
IPHONEOS_DEPLOYMENT_TARGET = 10.0;

MockerTests/MockerTests.swift

+26-1
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,32 @@ final class MockerTests: XCTestCase {
346346
request.httpMethod = Mock.HTTPMethod.put.rawValue
347347
XCTAssertNotNil(Mocker.mock(for: request))
348348
}
349+
350+
/// It should call the on request expectation.
351+
func testOnRequestExpectation() {
352+
let url = URL(string: "https://www.fakeurl.com")!
353+
354+
var mock = Mock(url: url, dataType: .json, statusCode: 200, data: [.get: Data()])
355+
let expectation = expectationForRequestingMock(&mock)
356+
mock.register()
357+
358+
URLSession.shared.dataTask(with: URLRequest(url: url)).resume()
359+
360+
wait(for: [expectation], timeout: 2.0)
361+
}
362+
363+
/// It should call the on completion expectation.
364+
func testOnCompletionExpectation() {
365+
let url = URL(string: "https://www.fakeurl.com")!
366+
367+
var mock = Mock(url: url, dataType: .json, statusCode: 200, data: [.get: Data()])
368+
let expectation = expectationForCompletingMock(&mock)
369+
mock.register()
370+
371+
URLSession.shared.dataTask(with: URLRequest(url: url)).resume()
372+
373+
wait(for: [expectation], timeout: 2.0)
374+
}
349375

350376
/// it should return the error we requested from the mock when we pass in an Error.
351377
func testMockReturningError() {
@@ -374,6 +400,5 @@ final class MockerTests: XCTestCase {
374400
}.resume()
375401

376402
waitForExpectations(timeout: 10.0, handler: nil)
377-
378403
}
379404
}

README.md

+30-16
Original file line numberDiff line numberDiff line change
@@ -188,22 +188,6 @@ let ignoredURL = URL(string: "www.wetransfer.com")!
188188
Mocker.ignore(ignoredURL)
189189
```
190190

191-
##### Mock callbacks
192-
You can register on `Mock` callbacks to make testing easier.
193-
194-
```swift
195-
var mock = Mock(url: request.url!, dataType: .json, statusCode: 200, data: [.post: Data()])
196-
mock.onRequest = { request, postBodyArguments in
197-
XCTAssertEqual(request.url, mock.request.url)
198-
XCTAssertEqual(expectedParameters, postBodyArguments as? [String: String])
199-
onRequestExpectation.fulfill()
200-
}
201-
mock.completion = {
202-
endpointIsCalledExpectation.fulfill()
203-
}
204-
mock.register()
205-
```
206-
207191
##### Mock errors
208192

209193
You can request a `Mock` to return an error, allowing testing of error handling.
@@ -227,6 +211,36 @@ URLSession.shared.dataTask(with: originalURL) { (data, urlresponse, err) in
227211
}.resume()
228212
```
229213

214+
##### Mock callbacks
215+
You can register on `Mock` callbacks to make testing easier.
216+
217+
```swift
218+
var mock = Mock(url: request.url!, dataType: .json, statusCode: 200, data: [.post: Data()])
219+
mock.onRequest = { request, postBodyArguments in
220+
XCTAssertEqual(request.url, mock.request.url)
221+
XCTAssertEqual(expectedParameters, postBodyArguments as? [String: String])
222+
onRequestExpectation.fulfill()
223+
}
224+
mock.completion = {
225+
endpointIsCalledExpectation.fulfill()
226+
}
227+
mock.register()
228+
```
229+
230+
##### Mock expectations
231+
Instead of setting the `completion` and `onRequest` you can also make use of expectations:
232+
233+
```swift
234+
var mock = Mock(url: url, dataType: .json, statusCode: 200, data: [.get: Data()])
235+
let requestExpectation = expectationForCompletingMock(&mock)
236+
let completionExpectation = expectationForCompletingMock(&mock)
237+
mock.register()
238+
239+
URLSession.shared.dataTask(with: URLRequest(url: url)).resume()
240+
241+
wait(for: [requestExpectation, completionExpectation], timeout: 2.0)
242+
```
243+
230244
## Communication
231245

232246
- If you **found a bug**, open an issue.

Sources/Mock.swift

+7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// swiftlint:disable force_unwrapping
1010

1111
import Foundation
12+
import XCTest
1213

1314
/// A Mock which can be used for mocking data requests with the `Mocker` by calling `Mocker.register(...)`.
1415
public struct Mock: Equatable {
@@ -103,6 +104,12 @@ public struct Mock: Equatable {
103104

104105
/// The callback which will be executed everytime this `Mock` was started. Can be used within unit tests for validating that a request has been started. The callback must be set before calling `register`.
105106
public var onRequest: OnRequest?
107+
108+
/// Can only be set internally as it's used by the `expectationForRequestingMock(_:)` method.
109+
var onRequestExpectation: XCTestExpectation?
110+
111+
/// Can only be set internally as it's used by the `expectationForCompletingMock(_:)` method.
112+
var onCompletedExpectation: XCTestExpectation?
106113

107114
private init(url: URL? = nil, ignoreQuery: Bool = false, dataType: DataType, statusCode: Int, data: [HTTPMethod: Data], requestError: Error? = nil, additionalHeaders: [String: String] = [:], fileExtensions: [String]? = nil) {
108115
self.urlToMock = url

Sources/MockingURLProtocol.swift

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public final class MockingURLProtocol: URLProtocol {
4646
if let onRequest = mock.onRequest {
4747
onRequest(request, request.postBodyArguments)
4848
}
49+
mock.onRequestExpectation?.fulfill()
4950

5051
guard let delay = mock.delay else {
5152
finishRequest(for: mock, data: data, response: response)
@@ -72,6 +73,7 @@ public final class MockingURLProtocol: URLProtocol {
7273
}
7374

7475
mock.completion?()
76+
mock.onCompletedExpectation?.fulfill()
7577
}
7678

7779
/// Implementation does nothing, but is needed for a valid inheritance of URLProtocol.

Sources/XCTest+Mocker.swift

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// XCTest+Mocker.swift
3+
// Mocker
4+
//
5+
// Created by Antoine van der Lee on 27/05/2020.
6+
// Copyright © 2020 WeTransfer. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import XCTest
11+
12+
public extension XCTestCase {
13+
func expectationForRequestingMock(_ mock: inout Mock) -> XCTestExpectation {
14+
let mockExpectation = expectation(description: "\(mock) should be requested")
15+
mock.onRequestExpectation = mockExpectation
16+
return mockExpectation
17+
}
18+
19+
func expectationForCompletingMock(_ mock: inout Mock) -> XCTestExpectation {
20+
let mockExpectation = expectation(description: "\(mock) should be finishing")
21+
mock.onCompletedExpectation = mockExpectation
22+
return mockExpectation
23+
}
24+
}

0 commit comments

Comments
 (0)