├── .gitignore
├── .sourcery.yml
├── .swift-version
├── .travis.yml
├── Example
├── Podfile
├── Podfile.lock
├── RoboKittenTests
│ ├── Info.plist
│ ├── Mocks
│ │ └── Generated
│ │ │ └── Mock.generated.swift
│ └── RoboKittenControllerSpec.swift
├── SwiftyMock.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ ├── SwiftyMock-Example.xcscheme
│ │ └── SwiftyMock-Tests.xcscheme
├── SwiftyMock.xcworkspace
│ └── contents.xcworkspacedata
├── SwiftyMock
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ │ ├── LaunchScreen.xib
│ │ └── Main.storyboard
│ ├── Images.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Info.plist
│ ├── RoboKitten
│ │ ├── Implementations
│ │ │ └── RoboKittenV1.swift
│ │ ├── RoboKitten.swift
│ │ └── RoboKittenController.swift
│ └── ViewController.swift
└── Tests
│ ├── Calls
│ ├── ReactiveMatchers.swift
│ ├── SwiftyMockCallsSpec.swift
│ └── SwiftyMockReactiveCallsSpec.swift
│ └── Info.plist
├── LICENSE
├── README.md
├── SwiftyMock.podspec
├── SwiftyMock
├── Assets
│ └── .gitkeep
├── Classes
│ ├── .gitkeep
│ ├── Core
│ │ └── MockUtils.swift
│ └── ReactiveCocoa
│ │ └── ReactiveExtensions.swift
└── Templates
│ └── Mock.stencil
└── _Pods.xcodeproj
/.gitignore:
--------------------------------------------------------------------------------
1 | Example/DerivedData
2 | Example/Pods
3 | Example/SwiftyMock.xcodeproj/xcuserdata
4 | Example/SwiftyMock.xcworkspace/xcuserdata
5 | Example/.idea
6 | .DS_Store
7 | *.un~
8 |
--------------------------------------------------------------------------------
/.sourcery.yml:
--------------------------------------------------------------------------------
1 | sources:
2 | - ./Example/SwiftyMock/RoboKitten
3 | templates:
4 | - ./SwiftyMock/Templates
5 | output:
6 | path: ./Example/RoboKittenTests/Mocks/Generated
7 | args:
8 | testable: SwiftyMock_Example
--------------------------------------------------------------------------------
/.swift-version:
--------------------------------------------------------------------------------
1 | 4.1
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # references:
2 | # * http://www.objc.io/issue-6/travis-ci.html
3 | # * https://github.com/supermarin/xcpretty#usage
4 |
5 | osx_image: xcode9.4
6 |
7 | language: objective-c
8 | cache: cocoapods
9 | podfile: Example/Podfile
10 |
11 | before_install:
12 | - pod repo update --silent
13 | - pod update --project-directory=Example
14 | - pod install --project-directory=Example
15 |
16 | install:
17 | - gem install xcpretty --no-rdoc --no-ri --no-document --quiet
18 |
19 | script:
20 | - set -o pipefail && xcodebuild test -workspace Example/SwiftyMock.xcworkspace -scheme SwiftyMock-Tests -sdk iphonesimulator11.4 -destination 'platform=iOS Simulator,name=iPhone 6,OS=11.4' | xcpretty -c
21 | - pod lib lint --quick --allow-warnings
22 |
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, '9.3'
2 | use_frameworks!
3 | #inhibit_all_warnings!
4 |
5 | def reusePods
6 | pod 'SwiftyMock/ReactiveCocoa', :path => '../'
7 | end
8 |
9 | def reuseTestPods
10 | reusePods
11 | pod 'Quick', '~> 1.2'
12 | # using 7.x-branch for now because of this issue fix https://github.com/Quick/Nimble/issues/478
13 | # switch to corresponding version once it's released
14 | pod 'Nimble', :git => 'https://github.com/Quick/Nimble', :branch => '7.x-branch'
15 | end
16 |
17 | target 'SwiftyMock_Example' do
18 | reusePods
19 | end
20 |
21 | target 'SwiftyMock_Tests' do
22 | reuseTestPods
23 | end
24 |
25 | target 'RoboKittenTests' do
26 | reuseTestPods
27 | end
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Example/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Nimble (7.1.2)
3 | - Quick (1.3.0)
4 | - ReactiveCocoa (7.1.0):
5 | - ReactiveSwift (~> 3.1)
6 | - ReactiveSwift (3.1.0):
7 | - Result (~> 3.2)
8 | - Result (3.2.4)
9 | - SwiftyMock/Core (0.2.3)
10 | - SwiftyMock/ReactiveCocoa (0.2.3):
11 | - ReactiveCocoa (~> 7.1)
12 | - SwiftyMock/Core
13 |
14 | DEPENDENCIES:
15 | - Nimble (from `https://github.com/Quick/Nimble`, branch `7.x-branch`)
16 | - Quick (~> 1.2)
17 | - SwiftyMock/ReactiveCocoa (from `../`)
18 |
19 | SPEC REPOS:
20 | https://github.com/cocoapods/specs.git:
21 | - Quick
22 | - ReactiveCocoa
23 | - ReactiveSwift
24 | - Result
25 |
26 | EXTERNAL SOURCES:
27 | Nimble:
28 | :branch: 7.x-branch
29 | :git: https://github.com/Quick/Nimble
30 | SwiftyMock:
31 | :path: "../"
32 |
33 | CHECKOUT OPTIONS:
34 | Nimble:
35 | :commit: 773bc7b5b8f3be2ba7ba9d52c6e38936dd393f69
36 | :git: https://github.com/Quick/Nimble
37 |
38 | SPEC CHECKSUMS:
39 | Nimble: c0980a3cf3e9d3b8774ef08167a47bede81cf84f
40 | Quick: 03278013f71aa05fe9ecabc94fbcc6835f1ee76f
41 | ReactiveCocoa: 105ad96f6b8711f1ee7d165fc96587479298053b
42 | ReactiveSwift: 5b26d2e988fe0eed2daf48c4054d1de74db50184
43 | Result: d2d07204ce72856f1fd9130bbe42c35a7b0fea10
44 | SwiftyMock: 7ee122cdeb33302fff589ad3400085f464ccd292
45 |
46 | PODFILE CHECKSUM: 96e31c8bbe54905dd223cce795d28a49935d24a1
47 |
48 | COCOAPODS: 1.5.3
49 |
--------------------------------------------------------------------------------
/Example/RoboKittenTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Example/RoboKittenTests/Mocks/Generated/Mock.generated.swift:
--------------------------------------------------------------------------------
1 | // Generated using Sourcery 0.13.1 — https://github.com/krzysztofzablocki/Sourcery
2 | // DO NOT EDIT
3 |
4 | import Foundation
5 | import SwiftyMock
6 | @testable import SwiftyMock_Example
7 |
8 | class FakeLazyRoboKitten: LazyRoboKitten {
9 | let needsRestGetCall = FunctionVoidCall()
10 | let needsRestSetCall = FunctionCall()
11 | var needsRest: Bool {
12 | get { return stubCall(needsRestGetCall) }
13 | set { stubCall(needsRestSetCall, argument: newValue) }
14 | }
15 |
16 | let batteryStatusCall = FunctionVoidCall()
17 | func batteryStatus() -> Int {
18 | return stubCall(batteryStatusCall)
19 | }
20 |
21 | let jumpCall = FunctionCall<(x: Int, y: Int), Void>()
22 | func jump(x: Int, y: Int) {
23 | return stubCall(jumpCall, argument: (x: x, y: y), defaultValue: ())
24 | }
25 |
26 | let canJumpAtCall = FunctionCall<(x: Int, y: Int), Bool>()
27 | func canJumpAt(x: Int, y: Int) -> Bool {
28 | return stubCall(canJumpAtCall, argument: (x: x, y: y))
29 | }
30 |
31 | let restCall = FunctionCall<(Bool) -> (), Void>()
32 | func rest(_ completed: @escaping (Bool) -> ()) {
33 | return stubCall(restCall, argument: completed, defaultValue: ())
34 | }
35 | }
36 |
37 | class FakeRoboKitten: RoboKitten {
38 |
39 | let batteryStatusCall = FunctionVoidCall()
40 | func batteryStatus() -> Int {
41 | return stubCall(batteryStatusCall)
42 | }
43 |
44 | let jumpCall = FunctionCall<(x: Int, y: Int), Void>()
45 | func jump(x: Int, y: Int) {
46 | return stubCall(jumpCall, argument: (x: x, y: y), defaultValue: ())
47 | }
48 |
49 | let canJumpAtCall = FunctionCall<(x: Int, y: Int), Bool>()
50 | func canJumpAt(x: Int, y: Int) -> Bool {
51 | return stubCall(canJumpAtCall, argument: (x: x, y: y))
52 | }
53 |
54 | let restCall = FunctionCall<(Bool) -> (), Void>()
55 | func rest(_ completed: @escaping (Bool) -> ()) {
56 | return stubCall(restCall, argument: completed, defaultValue: ())
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Example/RoboKittenTests/RoboKittenControllerSpec.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RoboKittenControllerSpec.swift
3 | // SwiftyMock
4 | //
5 | // Created by Paul Taykalo on 7/31/16.
6 | // Copyright © 2016 CocoaPods. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | @testable import SwiftyMock_Example
11 |
12 | import Quick
13 | import Nimble
14 | import SwiftyMock
15 |
16 | class RoboKittenControllerSpec: QuickSpec {
17 | override func spec() {
18 | describe("RoboKittenController") {
19 | var sut: RoboKittenController!
20 | var kittenMock: FakeRoboKitten!
21 | beforeEach {
22 | kittenMock = FakeRoboKitten()
23 | sut = RoboKittenController(kitten: kittenMock)
24 | }
25 |
26 | describe("when checked for battery status") {
27 | it("should return LOW battery status for battery level < 10") {
28 | kittenMock.batteryStatusCall.returns(5)
29 | expect(sut.batteryStatus()).to(equal(BatteyStatus.low))
30 | }
31 | it("should return FULL battery status for battery level >= 100") {
32 | kittenMock.batteryStatusCall.returns(100)
33 | expect(sut.batteryStatus()).to(equal(BatteyStatus.full))
34 |
35 | kittenMock.batteryStatusCall.returns(210)
36 | expect(sut.batteryStatus()).to(equal(BatteyStatus.full))
37 | }
38 |
39 | it("should return NORMAL battery status for battery level between 10..100") {
40 | kittenMock.batteryStatusCall.returns(15)
41 | expect(sut.batteryStatus()).to(equal(BatteyStatus.normal))
42 |
43 | kittenMock.batteryStatusCall.returns(30)
44 | expect(sut.batteryStatus()).to(equal(BatteyStatus.normal))
45 | }
46 | }
47 |
48 | describe("when asked to jump somewhere") {
49 | beforeEach {
50 | kittenMock.canJumpAtCall.returns(false)
51 | }
52 | it("should ask kitten if it's available to jump there") {
53 | sut.jumpAt(x: 10, y: 20)
54 | expect(kittenMock.canJumpAtCall.called).to(beTruthy())
55 | }
56 |
57 | it("should ask kitten if it's available to jump there with the same coords") {
58 | sut.jumpAt(x: 10, y: 20)
59 | expect(kittenMock.canJumpAtCall.capturedArgument?.x).to(equal(10))
60 | expect(kittenMock.canJumpAtCall.capturedArgument?.y).to(equal(20))
61 | }
62 |
63 | context("and kitten can jump there") {
64 | beforeEach {
65 | kittenMock.canJumpAtCall.returns(true)
66 | }
67 | it("should actually ask kitten to jump") {
68 | sut.jumpAt(x: 15, y: 30)
69 | expect(kittenMock.jumpCall.called).to(beTruthy())
70 | expect(kittenMock.jumpCall.capturedArgument?.x).to(equal(15))
71 | expect(kittenMock.jumpCall.capturedArgument?.y).to(equal(30))
72 | }
73 |
74 | it("should actually ask kitten to jump only once per call") {
75 | sut.jumpAt(x: 18, y: 23)
76 | expect(kittenMock.jumpCall.callsCount).to(equal(1))
77 |
78 | sut.jumpAt(x: 80, y: 15)
79 | expect(kittenMock.jumpCall.callsCount).to(equal(2))
80 | }
81 |
82 | it("return success result") {
83 | expect(sut.jumpAt(x: 10, y: 20)).to(equal(Result.success))
84 | }
85 | }
86 |
87 | context("and kitten cannot jump there") {
88 | beforeEach {
89 | kittenMock.canJumpAtCall.returns(false)
90 | }
91 |
92 | it("should shouldn't ask kitten to jump") {
93 | sut.jumpAt(x: 15, y: 30)
94 | expect(kittenMock.jumpCall.called).to(beFalsy())
95 | }
96 | it("shouldreturn failure result") {
97 | expect(sut.jumpAt(x: 10, y: 20)).to(equal(Result.failure))
98 | }
99 | }
100 |
101 | }
102 |
103 | describe("when asked to perform multiple jumps") {
104 | context("and kitten can perform all of them") {
105 | beforeEach {
106 | kittenMock.canJumpAtCall.returns(true)
107 | }
108 | it("should return success result") {
109 | expect(sut.jump(inSequence: [(x: 10, y: 20), (x: 12, y: 20)])).to(equal(Result.success))
110 | }
111 |
112 | it("should call jump on each passed parameter in the correct order") {
113 | let sequence = [(x: 15, y: 21), (x: 23, y: 21)]
114 | sut.jump(inSequence: sequence)
115 | expect(kittenMock.jumpCall.callsCount).to(equal(2))
116 | expect(kittenMock.jumpCall.capturedArguments[0].x).to(equal(15))
117 | expect(kittenMock.jumpCall.capturedArguments[0].y).to(equal(21))
118 |
119 | expect(kittenMock.jumpCall.capturedArguments[1].x).to(equal(23))
120 | expect(kittenMock.jumpCall.capturedArguments[1].y).to(equal(21))
121 | }
122 | }
123 |
124 | context("And kitten can not jump at some coordinates") {
125 | beforeEach {
126 | kittenMock.canJumpAtCall
127 | .on { $0.x < 0 }.returns(false)
128 | .on { $0.y < 0 }.returns(false)
129 | .returns(true) // in all other cases
130 |
131 | }
132 | context("and there are some coordinates where kitten cannot jump at in passed in sequence") {
133 | it("should return failure result") {
134 | expect(sut.jump(inSequence: [(x: -10, y: 20), (x: 12, y: 20)])).to(equal(Result.failure))
135 | expect(sut.jump(inSequence: [(x: 10, y: -20), (x: 12, y: 20)])).to(equal(Result.failure))
136 | expect(sut.jump(inSequence: [(x: 10, y: -20), (x: -12, y: 20)])).to(equal(Result.failure))
137 | expect(sut.jump(inSequence: [(x: 10, y: -20), (x: 12, y: -20)])).to(equal(Result.failure))
138 | }
139 | it("should not ask kitten to jump at all") {
140 | sut.jump(inSequence: [(x: -10, y: 20), (x: 12, y: 20)])
141 |
142 | expect(kittenMock.jumpCall.called).to(beFalsy())
143 | }
144 | }
145 |
146 | context("and there are no coordinates where kitten cannot jump at in passed in sequence") {
147 | it("should return success result in case if there's no coords where kittent cannot jump at") {
148 | expect(sut.jump(inSequence: [(x: 10, y: 20), (x: 12, y: 20)])).to(equal(Result.success))
149 | }
150 | }
151 | }
152 | }
153 |
154 | context("when asked to rest") {
155 |
156 | it("should ask kitten to rest") {
157 | sut.rest { _ in }
158 | expect(kittenMock.restCall.called).to(beTruthy())
159 | }
160 |
161 | context("and kitten rests successfully") {
162 | beforeEach {
163 | kittenMock.restCall.performs { completion in
164 | completion(true)
165 | }
166 | }
167 | it("should return successful result") {
168 | var result: Result?
169 | sut.rest { restResult in
170 | result = restResult
171 | }
172 | expect(result).to(equal(.success))
173 | }
174 | }
175 |
176 | context("and kitten fails to rest") {
177 | beforeEach {
178 | kittenMock.restCall.performs { completion in
179 | completion(false)
180 | }
181 | }
182 | it("should return failure result") {
183 | var result: Result?
184 | sut.rest { restResult in
185 | result = restResult
186 | }
187 | expect(result).to(equal(.failure))
188 | }
189 | }
190 |
191 | }
192 | }
193 | }
194 | }
195 |
196 |
--------------------------------------------------------------------------------
/Example/SwiftyMock.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 4ED4AA41E4DD3980A4CD50F8 /* Pods_SwiftyMock_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F2E0186E90C589DC306B4DE9 /* Pods_SwiftyMock_Example.framework */; };
11 | 5BF3C0823C995244ED8DE121 /* Pods_SwiftyMock_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 86B1369ECEBF34CBD8BF24A7 /* Pods_SwiftyMock_Tests.framework */; };
12 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; };
13 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; };
14 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; };
15 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; };
16 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; };
17 | A7D119AA1D500828F6B64159 /* Pods_RoboKittenTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A380849D11951D85498E493C /* Pods_RoboKittenTests.framework */; };
18 | D21AF4631FC62DF600C0DC5F /* SwiftyMockReactiveCallsSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21AF4611FC62CFF00C0DC5F /* SwiftyMockReactiveCallsSpec.swift */; };
19 | D21AF4661FC638F200C0DC5F /* ReactiveMatchers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21AF4641FC6324400C0DC5F /* ReactiveMatchers.swift */; };
20 | D2AEE57F20F9559000FF7DC8 /* Mock.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2AEE57E20F9559000FF7DC8 /* Mock.generated.swift */; };
21 | E434BE281D4AAE86000E7125 /* SwiftyMockCallsSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = E434BE271D4AAE86000E7125 /* SwiftyMockCallsSpec.swift */; };
22 | E481D6901D4DDE61000E73AE /* RoboKittenControllerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = E481D68F1D4DDE61000E73AE /* RoboKittenControllerSpec.swift */; };
23 | EEDBE358155D115C15126670 /* RoboKitten.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEDBEBCC4DF10B0C24246892 /* RoboKitten.swift */; };
24 | EEDBE98564CE5D2A54750BFD /* RoboKittenV1.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEDBE0C70C380389995EB816 /* RoboKittenV1.swift */; };
25 | EEDBEAB8D9887C15ED1D0632 /* RoboKittenController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEDBE8EC7249C454D04FB152 /* RoboKittenController.swift */; };
26 | /* End PBXBuildFile section */
27 |
28 | /* Begin PBXContainerItemProxy section */
29 | 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = {
30 | isa = PBXContainerItemProxy;
31 | containerPortal = 607FACC81AFB9204008FA782 /* Project object */;
32 | proxyType = 1;
33 | remoteGlobalIDString = 607FACCF1AFB9204008FA782;
34 | remoteInfo = SwiftyMock;
35 | };
36 | E481D6881D4DDDBE000E73AE /* PBXContainerItemProxy */ = {
37 | isa = PBXContainerItemProxy;
38 | containerPortal = 607FACC81AFB9204008FA782 /* Project object */;
39 | proxyType = 1;
40 | remoteGlobalIDString = 607FACCF1AFB9204008FA782;
41 | remoteInfo = SwiftyMock_Example;
42 | };
43 | /* End PBXContainerItemProxy section */
44 |
45 | /* Begin PBXFileReference section */
46 | 3E6C27CCCE1CA5F8417EB860 /* Pods-SwiftyMock_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftyMock_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftyMock_Example/Pods-SwiftyMock_Example.release.xcconfig"; sourceTree = ""; };
47 | 56FDD6DA44AC86C2E1654D1A /* Pods-SwiftyMock_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftyMock_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftyMock_Tests/Pods-SwiftyMock_Tests.debug.xcconfig"; sourceTree = ""; };
48 | 607FACD01AFB9204008FA782 /* SwiftyMock_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftyMock_Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
49 | 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
50 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
51 | 607FACD71AFB9204008FA782 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
52 | 607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
53 | 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
54 | 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
55 | 607FACE51AFB9204008FA782 /* SwiftyMock_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftyMock_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
56 | 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
57 | 65CB55A6EFAA61CD166E6ABE /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; };
58 | 780C71DD02D492D34BF6DC2F /* Pods-RoboKittenTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RoboKittenTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RoboKittenTests/Pods-RoboKittenTests.debug.xcconfig"; sourceTree = ""; };
59 | 86B1369ECEBF34CBD8BF24A7 /* Pods_SwiftyMock_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwiftyMock_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
60 | 98A466BCCB5D6510F97AD7B2 /* SwiftyMock.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = SwiftyMock.podspec; path = ../SwiftyMock.podspec; sourceTree = ""; };
61 | A380849D11951D85498E493C /* Pods_RoboKittenTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RoboKittenTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
62 | BE3E75F38E5B31874FC7F8C4 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; };
63 | D21AF4611FC62CFF00C0DC5F /* SwiftyMockReactiveCallsSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftyMockReactiveCallsSpec.swift; sourceTree = ""; };
64 | D21AF4641FC6324400C0DC5F /* ReactiveMatchers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactiveMatchers.swift; sourceTree = ""; };
65 | D2AEE57E20F9559000FF7DC8 /* Mock.generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Mock.generated.swift; sourceTree = ""; };
66 | E434BE271D4AAE86000E7125 /* SwiftyMockCallsSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftyMockCallsSpec.swift; sourceTree = ""; };
67 | E481D6831D4DDDBE000E73AE /* RoboKittenTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RoboKittenTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
68 | E481D6871D4DDDBE000E73AE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
69 | E481D68F1D4DDE61000E73AE /* RoboKittenControllerSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoboKittenControllerSpec.swift; sourceTree = ""; };
70 | E6DD82C8225916729797ED83 /* Pods-RoboKittenTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RoboKittenTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RoboKittenTests/Pods-RoboKittenTests.release.xcconfig"; sourceTree = ""; };
71 | EEDBE0C70C380389995EB816 /* RoboKittenV1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoboKittenV1.swift; sourceTree = ""; };
72 | EEDBE8EC7249C454D04FB152 /* RoboKittenController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoboKittenController.swift; sourceTree = ""; };
73 | EEDBEBCC4DF10B0C24246892 /* RoboKitten.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoboKitten.swift; sourceTree = ""; };
74 | F2E0186E90C589DC306B4DE9 /* Pods_SwiftyMock_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwiftyMock_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
75 | F8922BE058C4D4604D03C886 /* Pods-SwiftyMock_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftyMock_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftyMock_Tests/Pods-SwiftyMock_Tests.release.xcconfig"; sourceTree = ""; };
76 | FC5C9C80564A568114ED28E1 /* Pods-SwiftyMock_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftyMock_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftyMock_Example/Pods-SwiftyMock_Example.debug.xcconfig"; sourceTree = ""; };
77 | /* End PBXFileReference section */
78 |
79 | /* Begin PBXFrameworksBuildPhase section */
80 | 607FACCD1AFB9204008FA782 /* Frameworks */ = {
81 | isa = PBXFrameworksBuildPhase;
82 | buildActionMask = 2147483647;
83 | files = (
84 | 4ED4AA41E4DD3980A4CD50F8 /* Pods_SwiftyMock_Example.framework in Frameworks */,
85 | );
86 | runOnlyForDeploymentPostprocessing = 0;
87 | };
88 | 607FACE21AFB9204008FA782 /* Frameworks */ = {
89 | isa = PBXFrameworksBuildPhase;
90 | buildActionMask = 2147483647;
91 | files = (
92 | 5BF3C0823C995244ED8DE121 /* Pods_SwiftyMock_Tests.framework in Frameworks */,
93 | );
94 | runOnlyForDeploymentPostprocessing = 0;
95 | };
96 | E481D6801D4DDDBE000E73AE /* Frameworks */ = {
97 | isa = PBXFrameworksBuildPhase;
98 | buildActionMask = 2147483647;
99 | files = (
100 | A7D119AA1D500828F6B64159 /* Pods_RoboKittenTests.framework in Frameworks */,
101 | );
102 | runOnlyForDeploymentPostprocessing = 0;
103 | };
104 | /* End PBXFrameworksBuildPhase section */
105 |
106 | /* Begin PBXGroup section */
107 | 607FACC71AFB9204008FA782 = {
108 | isa = PBXGroup;
109 | children = (
110 | 607FACF51AFB993E008FA782 /* Podspec Metadata */,
111 | 607FACD21AFB9204008FA782 /* Example for SwiftyMock */,
112 | 607FACE81AFB9204008FA782 /* Tests */,
113 | E481D6841D4DDDBE000E73AE /* RoboKittenTests */,
114 | 607FACD11AFB9204008FA782 /* Products */,
115 | D5147DA4ACDB782F513D0F5D /* Pods */,
116 | 873EEE7B7B336D48973398FC /* Frameworks */,
117 | );
118 | sourceTree = "";
119 | };
120 | 607FACD11AFB9204008FA782 /* Products */ = {
121 | isa = PBXGroup;
122 | children = (
123 | 607FACD01AFB9204008FA782 /* SwiftyMock_Example.app */,
124 | 607FACE51AFB9204008FA782 /* SwiftyMock_Tests.xctest */,
125 | E481D6831D4DDDBE000E73AE /* RoboKittenTests.xctest */,
126 | );
127 | name = Products;
128 | sourceTree = "";
129 | };
130 | 607FACD21AFB9204008FA782 /* Example for SwiftyMock */ = {
131 | isa = PBXGroup;
132 | children = (
133 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */,
134 | 607FACD71AFB9204008FA782 /* ViewController.swift */,
135 | 607FACD91AFB9204008FA782 /* Main.storyboard */,
136 | 607FACDC1AFB9204008FA782 /* Images.xcassets */,
137 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */,
138 | 607FACD31AFB9204008FA782 /* Supporting Files */,
139 | EEDBEEADC2A4E4ED70D52927 /* RoboKitten */,
140 | );
141 | name = "Example for SwiftyMock";
142 | path = SwiftyMock;
143 | sourceTree = "";
144 | };
145 | 607FACD31AFB9204008FA782 /* Supporting Files */ = {
146 | isa = PBXGroup;
147 | children = (
148 | 607FACD41AFB9204008FA782 /* Info.plist */,
149 | );
150 | name = "Supporting Files";
151 | sourceTree = "";
152 | };
153 | 607FACE81AFB9204008FA782 /* Tests */ = {
154 | isa = PBXGroup;
155 | children = (
156 | E434BE261D4AAE4A000E7125 /* Calls */,
157 | 607FACE91AFB9204008FA782 /* Supporting Files */,
158 | );
159 | path = Tests;
160 | sourceTree = "";
161 | };
162 | 607FACE91AFB9204008FA782 /* Supporting Files */ = {
163 | isa = PBXGroup;
164 | children = (
165 | 607FACEA1AFB9204008FA782 /* Info.plist */,
166 | );
167 | name = "Supporting Files";
168 | sourceTree = "";
169 | };
170 | 607FACF51AFB993E008FA782 /* Podspec Metadata */ = {
171 | isa = PBXGroup;
172 | children = (
173 | 98A466BCCB5D6510F97AD7B2 /* SwiftyMock.podspec */,
174 | BE3E75F38E5B31874FC7F8C4 /* README.md */,
175 | 65CB55A6EFAA61CD166E6ABE /* LICENSE */,
176 | );
177 | name = "Podspec Metadata";
178 | sourceTree = "";
179 | };
180 | 873EEE7B7B336D48973398FC /* Frameworks */ = {
181 | isa = PBXGroup;
182 | children = (
183 | F2E0186E90C589DC306B4DE9 /* Pods_SwiftyMock_Example.framework */,
184 | 86B1369ECEBF34CBD8BF24A7 /* Pods_SwiftyMock_Tests.framework */,
185 | A380849D11951D85498E493C /* Pods_RoboKittenTests.framework */,
186 | );
187 | name = Frameworks;
188 | sourceTree = "";
189 | };
190 | D2AEE57D20F9559000FF7DC8 /* Generated */ = {
191 | isa = PBXGroup;
192 | children = (
193 | D2AEE57E20F9559000FF7DC8 /* Mock.generated.swift */,
194 | );
195 | path = Generated;
196 | sourceTree = "";
197 | };
198 | D5147DA4ACDB782F513D0F5D /* Pods */ = {
199 | isa = PBXGroup;
200 | children = (
201 | FC5C9C80564A568114ED28E1 /* Pods-SwiftyMock_Example.debug.xcconfig */,
202 | 3E6C27CCCE1CA5F8417EB860 /* Pods-SwiftyMock_Example.release.xcconfig */,
203 | 56FDD6DA44AC86C2E1654D1A /* Pods-SwiftyMock_Tests.debug.xcconfig */,
204 | F8922BE058C4D4604D03C886 /* Pods-SwiftyMock_Tests.release.xcconfig */,
205 | 780C71DD02D492D34BF6DC2F /* Pods-RoboKittenTests.debug.xcconfig */,
206 | E6DD82C8225916729797ED83 /* Pods-RoboKittenTests.release.xcconfig */,
207 | );
208 | name = Pods;
209 | sourceTree = "";
210 | };
211 | E434BE261D4AAE4A000E7125 /* Calls */ = {
212 | isa = PBXGroup;
213 | children = (
214 | E434BE271D4AAE86000E7125 /* SwiftyMockCallsSpec.swift */,
215 | D21AF4611FC62CFF00C0DC5F /* SwiftyMockReactiveCallsSpec.swift */,
216 | D21AF4641FC6324400C0DC5F /* ReactiveMatchers.swift */,
217 | );
218 | path = Calls;
219 | sourceTree = "";
220 | };
221 | E481D6841D4DDDBE000E73AE /* RoboKittenTests */ = {
222 | isa = PBXGroup;
223 | children = (
224 | E481D6871D4DDDBE000E73AE /* Info.plist */,
225 | E481D68F1D4DDE61000E73AE /* RoboKittenControllerSpec.swift */,
226 | EEDBE0EC744C4D09DA6A1963 /* Mocks */,
227 | );
228 | path = RoboKittenTests;
229 | sourceTree = "";
230 | };
231 | EEDBE0EC744C4D09DA6A1963 /* Mocks */ = {
232 | isa = PBXGroup;
233 | children = (
234 | D2AEE57D20F9559000FF7DC8 /* Generated */,
235 | );
236 | path = Mocks;
237 | sourceTree = "";
238 | };
239 | EEDBE37BD3F93F1EE0988A08 /* Implementations */ = {
240 | isa = PBXGroup;
241 | children = (
242 | EEDBE0C70C380389995EB816 /* RoboKittenV1.swift */,
243 | );
244 | path = Implementations;
245 | sourceTree = "";
246 | };
247 | EEDBEEADC2A4E4ED70D52927 /* RoboKitten */ = {
248 | isa = PBXGroup;
249 | children = (
250 | EEDBEBCC4DF10B0C24246892 /* RoboKitten.swift */,
251 | EEDBE8EC7249C454D04FB152 /* RoboKittenController.swift */,
252 | EEDBE37BD3F93F1EE0988A08 /* Implementations */,
253 | );
254 | path = RoboKitten;
255 | sourceTree = "";
256 | };
257 | /* End PBXGroup section */
258 |
259 | /* Begin PBXNativeTarget section */
260 | 607FACCF1AFB9204008FA782 /* SwiftyMock_Example */ = {
261 | isa = PBXNativeTarget;
262 | buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "SwiftyMock_Example" */;
263 | buildPhases = (
264 | C32EF44E3C05F3402819F3E1 /* [CP] Check Pods Manifest.lock */,
265 | 607FACCC1AFB9204008FA782 /* Sources */,
266 | 607FACCD1AFB9204008FA782 /* Frameworks */,
267 | 607FACCE1AFB9204008FA782 /* Resources */,
268 | 6A3F6B608A6F4760DAAA542E /* [CP] Embed Pods Frameworks */,
269 | );
270 | buildRules = (
271 | );
272 | dependencies = (
273 | );
274 | name = SwiftyMock_Example;
275 | productName = SwiftyMock;
276 | productReference = 607FACD01AFB9204008FA782 /* SwiftyMock_Example.app */;
277 | productType = "com.apple.product-type.application";
278 | };
279 | 607FACE41AFB9204008FA782 /* SwiftyMock_Tests */ = {
280 | isa = PBXNativeTarget;
281 | buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "SwiftyMock_Tests" */;
282 | buildPhases = (
283 | 076287B0FFA270C0D181F7BF /* [CP] Check Pods Manifest.lock */,
284 | 607FACE11AFB9204008FA782 /* Sources */,
285 | 607FACE21AFB9204008FA782 /* Frameworks */,
286 | 607FACE31AFB9204008FA782 /* Resources */,
287 | 409972991AA0686BA8B28E43 /* [CP] Embed Pods Frameworks */,
288 | );
289 | buildRules = (
290 | );
291 | dependencies = (
292 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */,
293 | );
294 | name = SwiftyMock_Tests;
295 | productName = Tests;
296 | productReference = 607FACE51AFB9204008FA782 /* SwiftyMock_Tests.xctest */;
297 | productType = "com.apple.product-type.bundle.unit-test";
298 | };
299 | E481D6821D4DDDBE000E73AE /* RoboKittenTests */ = {
300 | isa = PBXNativeTarget;
301 | buildConfigurationList = E481D68A1D4DDDBE000E73AE /* Build configuration list for PBXNativeTarget "RoboKittenTests" */;
302 | buildPhases = (
303 | 58C919E4579AAC652916579F /* [CP] Check Pods Manifest.lock */,
304 | E481D67F1D4DDDBE000E73AE /* Sources */,
305 | E481D6801D4DDDBE000E73AE /* Frameworks */,
306 | E481D6811D4DDDBE000E73AE /* Resources */,
307 | BECACC2C45CF5517A8987EB9 /* [CP] Embed Pods Frameworks */,
308 | );
309 | buildRules = (
310 | );
311 | dependencies = (
312 | E481D6891D4DDDBE000E73AE /* PBXTargetDependency */,
313 | );
314 | name = RoboKittenTests;
315 | productName = RoboKittenTests;
316 | productReference = E481D6831D4DDDBE000E73AE /* RoboKittenTests.xctest */;
317 | productType = "com.apple.product-type.bundle.unit-test";
318 | };
319 | /* End PBXNativeTarget section */
320 |
321 | /* Begin PBXProject section */
322 | 607FACC81AFB9204008FA782 /* Project object */ = {
323 | isa = PBXProject;
324 | attributes = {
325 | LastSwiftUpdateCheck = 0730;
326 | LastUpgradeCheck = 0830;
327 | ORGANIZATIONNAME = CocoaPods;
328 | TargetAttributes = {
329 | 607FACCF1AFB9204008FA782 = {
330 | CreatedOnToolsVersion = 6.3.1;
331 | LastSwiftMigration = 0830;
332 | };
333 | 607FACE41AFB9204008FA782 = {
334 | CreatedOnToolsVersion = 6.3.1;
335 | LastSwiftMigration = 0830;
336 | };
337 | E481D6821D4DDDBE000E73AE = {
338 | CreatedOnToolsVersion = 7.3.1;
339 | LastSwiftMigration = 0830;
340 | TestTargetID = 607FACCF1AFB9204008FA782;
341 | };
342 | };
343 | };
344 | buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "SwiftyMock" */;
345 | compatibilityVersion = "Xcode 3.2";
346 | developmentRegion = English;
347 | hasScannedForEncodings = 0;
348 | knownRegions = (
349 | en,
350 | Base,
351 | );
352 | mainGroup = 607FACC71AFB9204008FA782;
353 | productRefGroup = 607FACD11AFB9204008FA782 /* Products */;
354 | projectDirPath = "";
355 | projectRoot = "";
356 | targets = (
357 | 607FACCF1AFB9204008FA782 /* SwiftyMock_Example */,
358 | 607FACE41AFB9204008FA782 /* SwiftyMock_Tests */,
359 | E481D6821D4DDDBE000E73AE /* RoboKittenTests */,
360 | );
361 | };
362 | /* End PBXProject section */
363 |
364 | /* Begin PBXResourcesBuildPhase section */
365 | 607FACCE1AFB9204008FA782 /* Resources */ = {
366 | isa = PBXResourcesBuildPhase;
367 | buildActionMask = 2147483647;
368 | files = (
369 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */,
370 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */,
371 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */,
372 | );
373 | runOnlyForDeploymentPostprocessing = 0;
374 | };
375 | 607FACE31AFB9204008FA782 /* Resources */ = {
376 | isa = PBXResourcesBuildPhase;
377 | buildActionMask = 2147483647;
378 | files = (
379 | );
380 | runOnlyForDeploymentPostprocessing = 0;
381 | };
382 | E481D6811D4DDDBE000E73AE /* Resources */ = {
383 | isa = PBXResourcesBuildPhase;
384 | buildActionMask = 2147483647;
385 | files = (
386 | );
387 | runOnlyForDeploymentPostprocessing = 0;
388 | };
389 | /* End PBXResourcesBuildPhase section */
390 |
391 | /* Begin PBXShellScriptBuildPhase section */
392 | 076287B0FFA270C0D181F7BF /* [CP] Check Pods Manifest.lock */ = {
393 | isa = PBXShellScriptBuildPhase;
394 | buildActionMask = 2147483647;
395 | files = (
396 | );
397 | inputPaths = (
398 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
399 | "${PODS_ROOT}/Manifest.lock",
400 | );
401 | name = "[CP] Check Pods Manifest.lock";
402 | outputPaths = (
403 | "$(DERIVED_FILE_DIR)/Pods-SwiftyMock_Tests-checkManifestLockResult.txt",
404 | );
405 | runOnlyForDeploymentPostprocessing = 0;
406 | shellPath = /bin/sh;
407 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
408 | showEnvVarsInLog = 0;
409 | };
410 | 409972991AA0686BA8B28E43 /* [CP] Embed Pods Frameworks */ = {
411 | isa = PBXShellScriptBuildPhase;
412 | buildActionMask = 2147483647;
413 | files = (
414 | );
415 | inputPaths = (
416 | "${SRCROOT}/Pods/Target Support Files/Pods-SwiftyMock_Tests/Pods-SwiftyMock_Tests-frameworks.sh",
417 | "${BUILT_PRODUCTS_DIR}/ReactiveCocoa/ReactiveCocoa.framework",
418 | "${BUILT_PRODUCTS_DIR}/ReactiveSwift/ReactiveSwift.framework",
419 | "${BUILT_PRODUCTS_DIR}/Result/Result.framework",
420 | "${BUILT_PRODUCTS_DIR}/SwiftyMock/SwiftyMock.framework",
421 | "${BUILT_PRODUCTS_DIR}/Nimble/Nimble.framework",
422 | "${BUILT_PRODUCTS_DIR}/Quick/Quick.framework",
423 | );
424 | name = "[CP] Embed Pods Frameworks";
425 | outputPaths = (
426 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactiveCocoa.framework",
427 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactiveSwift.framework",
428 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Result.framework",
429 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyMock.framework",
430 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Nimble.framework",
431 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Quick.framework",
432 | );
433 | runOnlyForDeploymentPostprocessing = 0;
434 | shellPath = /bin/sh;
435 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftyMock_Tests/Pods-SwiftyMock_Tests-frameworks.sh\"\n";
436 | showEnvVarsInLog = 0;
437 | };
438 | 58C919E4579AAC652916579F /* [CP] Check Pods Manifest.lock */ = {
439 | isa = PBXShellScriptBuildPhase;
440 | buildActionMask = 2147483647;
441 | files = (
442 | );
443 | inputPaths = (
444 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
445 | "${PODS_ROOT}/Manifest.lock",
446 | );
447 | name = "[CP] Check Pods Manifest.lock";
448 | outputPaths = (
449 | "$(DERIVED_FILE_DIR)/Pods-RoboKittenTests-checkManifestLockResult.txt",
450 | );
451 | runOnlyForDeploymentPostprocessing = 0;
452 | shellPath = /bin/sh;
453 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
454 | showEnvVarsInLog = 0;
455 | };
456 | 6A3F6B608A6F4760DAAA542E /* [CP] Embed Pods Frameworks */ = {
457 | isa = PBXShellScriptBuildPhase;
458 | buildActionMask = 2147483647;
459 | files = (
460 | );
461 | inputPaths = (
462 | "${SRCROOT}/Pods/Target Support Files/Pods-SwiftyMock_Example/Pods-SwiftyMock_Example-frameworks.sh",
463 | "${BUILT_PRODUCTS_DIR}/ReactiveCocoa/ReactiveCocoa.framework",
464 | "${BUILT_PRODUCTS_DIR}/ReactiveSwift/ReactiveSwift.framework",
465 | "${BUILT_PRODUCTS_DIR}/Result/Result.framework",
466 | "${BUILT_PRODUCTS_DIR}/SwiftyMock/SwiftyMock.framework",
467 | );
468 | name = "[CP] Embed Pods Frameworks";
469 | outputPaths = (
470 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactiveCocoa.framework",
471 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactiveSwift.framework",
472 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Result.framework",
473 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyMock.framework",
474 | );
475 | runOnlyForDeploymentPostprocessing = 0;
476 | shellPath = /bin/sh;
477 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftyMock_Example/Pods-SwiftyMock_Example-frameworks.sh\"\n";
478 | showEnvVarsInLog = 0;
479 | };
480 | BECACC2C45CF5517A8987EB9 /* [CP] Embed Pods Frameworks */ = {
481 | isa = PBXShellScriptBuildPhase;
482 | buildActionMask = 2147483647;
483 | files = (
484 | );
485 | inputPaths = (
486 | "${SRCROOT}/Pods/Target Support Files/Pods-RoboKittenTests/Pods-RoboKittenTests-frameworks.sh",
487 | "${BUILT_PRODUCTS_DIR}/ReactiveCocoa/ReactiveCocoa.framework",
488 | "${BUILT_PRODUCTS_DIR}/ReactiveSwift/ReactiveSwift.framework",
489 | "${BUILT_PRODUCTS_DIR}/Result/Result.framework",
490 | "${BUILT_PRODUCTS_DIR}/SwiftyMock/SwiftyMock.framework",
491 | "${BUILT_PRODUCTS_DIR}/Nimble/Nimble.framework",
492 | "${BUILT_PRODUCTS_DIR}/Quick/Quick.framework",
493 | );
494 | name = "[CP] Embed Pods Frameworks";
495 | outputPaths = (
496 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactiveCocoa.framework",
497 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactiveSwift.framework",
498 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Result.framework",
499 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyMock.framework",
500 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Nimble.framework",
501 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Quick.framework",
502 | );
503 | runOnlyForDeploymentPostprocessing = 0;
504 | shellPath = /bin/sh;
505 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RoboKittenTests/Pods-RoboKittenTests-frameworks.sh\"\n";
506 | showEnvVarsInLog = 0;
507 | };
508 | C32EF44E3C05F3402819F3E1 /* [CP] Check Pods Manifest.lock */ = {
509 | isa = PBXShellScriptBuildPhase;
510 | buildActionMask = 2147483647;
511 | files = (
512 | );
513 | inputPaths = (
514 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
515 | "${PODS_ROOT}/Manifest.lock",
516 | );
517 | name = "[CP] Check Pods Manifest.lock";
518 | outputPaths = (
519 | "$(DERIVED_FILE_DIR)/Pods-SwiftyMock_Example-checkManifestLockResult.txt",
520 | );
521 | runOnlyForDeploymentPostprocessing = 0;
522 | shellPath = /bin/sh;
523 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
524 | showEnvVarsInLog = 0;
525 | };
526 | /* End PBXShellScriptBuildPhase section */
527 |
528 | /* Begin PBXSourcesBuildPhase section */
529 | 607FACCC1AFB9204008FA782 /* Sources */ = {
530 | isa = PBXSourcesBuildPhase;
531 | buildActionMask = 2147483647;
532 | files = (
533 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */,
534 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */,
535 | EEDBE358155D115C15126670 /* RoboKitten.swift in Sources */,
536 | EEDBEAB8D9887C15ED1D0632 /* RoboKittenController.swift in Sources */,
537 | EEDBE98564CE5D2A54750BFD /* RoboKittenV1.swift in Sources */,
538 | );
539 | runOnlyForDeploymentPostprocessing = 0;
540 | };
541 | 607FACE11AFB9204008FA782 /* Sources */ = {
542 | isa = PBXSourcesBuildPhase;
543 | buildActionMask = 2147483647;
544 | files = (
545 | E434BE281D4AAE86000E7125 /* SwiftyMockCallsSpec.swift in Sources */,
546 | D21AF4661FC638F200C0DC5F /* ReactiveMatchers.swift in Sources */,
547 | D21AF4631FC62DF600C0DC5F /* SwiftyMockReactiveCallsSpec.swift in Sources */,
548 | );
549 | runOnlyForDeploymentPostprocessing = 0;
550 | };
551 | E481D67F1D4DDDBE000E73AE /* Sources */ = {
552 | isa = PBXSourcesBuildPhase;
553 | buildActionMask = 2147483647;
554 | files = (
555 | D2AEE57F20F9559000FF7DC8 /* Mock.generated.swift in Sources */,
556 | E481D6901D4DDE61000E73AE /* RoboKittenControllerSpec.swift in Sources */,
557 | );
558 | runOnlyForDeploymentPostprocessing = 0;
559 | };
560 | /* End PBXSourcesBuildPhase section */
561 |
562 | /* Begin PBXTargetDependency section */
563 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */ = {
564 | isa = PBXTargetDependency;
565 | target = 607FACCF1AFB9204008FA782 /* SwiftyMock_Example */;
566 | targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */;
567 | };
568 | E481D6891D4DDDBE000E73AE /* PBXTargetDependency */ = {
569 | isa = PBXTargetDependency;
570 | target = 607FACCF1AFB9204008FA782 /* SwiftyMock_Example */;
571 | targetProxy = E481D6881D4DDDBE000E73AE /* PBXContainerItemProxy */;
572 | };
573 | /* End PBXTargetDependency section */
574 |
575 | /* Begin PBXVariantGroup section */
576 | 607FACD91AFB9204008FA782 /* Main.storyboard */ = {
577 | isa = PBXVariantGroup;
578 | children = (
579 | 607FACDA1AFB9204008FA782 /* Base */,
580 | );
581 | name = Main.storyboard;
582 | sourceTree = "";
583 | };
584 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = {
585 | isa = PBXVariantGroup;
586 | children = (
587 | 607FACDF1AFB9204008FA782 /* Base */,
588 | );
589 | name = LaunchScreen.xib;
590 | sourceTree = "";
591 | };
592 | /* End PBXVariantGroup section */
593 |
594 | /* Begin XCBuildConfiguration section */
595 | 607FACED1AFB9204008FA782 /* Debug */ = {
596 | isa = XCBuildConfiguration;
597 | buildSettings = {
598 | ALWAYS_SEARCH_USER_PATHS = NO;
599 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
600 | CLANG_CXX_LIBRARY = "libc++";
601 | CLANG_ENABLE_MODULES = YES;
602 | CLANG_ENABLE_OBJC_ARC = YES;
603 | CLANG_WARN_BOOL_CONVERSION = YES;
604 | CLANG_WARN_CONSTANT_CONVERSION = YES;
605 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
606 | CLANG_WARN_EMPTY_BODY = YES;
607 | CLANG_WARN_ENUM_CONVERSION = YES;
608 | CLANG_WARN_INFINITE_RECURSION = YES;
609 | CLANG_WARN_INT_CONVERSION = YES;
610 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
611 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
612 | CLANG_WARN_UNREACHABLE_CODE = YES;
613 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
614 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
615 | COPY_PHASE_STRIP = NO;
616 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
617 | ENABLE_STRICT_OBJC_MSGSEND = YES;
618 | ENABLE_TESTABILITY = YES;
619 | GCC_C_LANGUAGE_STANDARD = gnu99;
620 | GCC_DYNAMIC_NO_PIC = NO;
621 | GCC_NO_COMMON_BLOCKS = YES;
622 | GCC_OPTIMIZATION_LEVEL = 0;
623 | GCC_PREPROCESSOR_DEFINITIONS = (
624 | "DEBUG=1",
625 | "$(inherited)",
626 | );
627 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
628 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
629 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
630 | GCC_WARN_UNDECLARED_SELECTOR = YES;
631 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
632 | GCC_WARN_UNUSED_FUNCTION = YES;
633 | GCC_WARN_UNUSED_VARIABLE = YES;
634 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
635 | MTL_ENABLE_DEBUG_INFO = YES;
636 | ONLY_ACTIVE_ARCH = YES;
637 | SDKROOT = iphoneos;
638 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
639 | };
640 | name = Debug;
641 | };
642 | 607FACEE1AFB9204008FA782 /* Release */ = {
643 | isa = XCBuildConfiguration;
644 | buildSettings = {
645 | ALWAYS_SEARCH_USER_PATHS = NO;
646 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
647 | CLANG_CXX_LIBRARY = "libc++";
648 | CLANG_ENABLE_MODULES = YES;
649 | CLANG_ENABLE_OBJC_ARC = YES;
650 | CLANG_WARN_BOOL_CONVERSION = YES;
651 | CLANG_WARN_CONSTANT_CONVERSION = YES;
652 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
653 | CLANG_WARN_EMPTY_BODY = YES;
654 | CLANG_WARN_ENUM_CONVERSION = YES;
655 | CLANG_WARN_INFINITE_RECURSION = YES;
656 | CLANG_WARN_INT_CONVERSION = YES;
657 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
658 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
659 | CLANG_WARN_UNREACHABLE_CODE = YES;
660 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
661 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
662 | COPY_PHASE_STRIP = NO;
663 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
664 | ENABLE_NS_ASSERTIONS = NO;
665 | ENABLE_STRICT_OBJC_MSGSEND = YES;
666 | GCC_C_LANGUAGE_STANDARD = gnu99;
667 | GCC_NO_COMMON_BLOCKS = YES;
668 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
669 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
670 | GCC_WARN_UNDECLARED_SELECTOR = YES;
671 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
672 | GCC_WARN_UNUSED_FUNCTION = YES;
673 | GCC_WARN_UNUSED_VARIABLE = YES;
674 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
675 | MTL_ENABLE_DEBUG_INFO = NO;
676 | SDKROOT = iphoneos;
677 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
678 | VALIDATE_PRODUCT = YES;
679 | };
680 | name = Release;
681 | };
682 | 607FACF01AFB9204008FA782 /* Debug */ = {
683 | isa = XCBuildConfiguration;
684 | baseConfigurationReference = FC5C9C80564A568114ED28E1 /* Pods-SwiftyMock_Example.debug.xcconfig */;
685 | buildSettings = {
686 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
687 | INFOPLIST_FILE = SwiftyMock/Info.plist;
688 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
689 | MODULE_NAME = ExampleApp;
690 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
691 | PRODUCT_NAME = "$(TARGET_NAME)";
692 | SWIFT_VERSION = 4.0;
693 | };
694 | name = Debug;
695 | };
696 | 607FACF11AFB9204008FA782 /* Release */ = {
697 | isa = XCBuildConfiguration;
698 | baseConfigurationReference = 3E6C27CCCE1CA5F8417EB860 /* Pods-SwiftyMock_Example.release.xcconfig */;
699 | buildSettings = {
700 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
701 | INFOPLIST_FILE = SwiftyMock/Info.plist;
702 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
703 | MODULE_NAME = ExampleApp;
704 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
705 | PRODUCT_NAME = "$(TARGET_NAME)";
706 | SWIFT_VERSION = 4.0;
707 | };
708 | name = Release;
709 | };
710 | 607FACF31AFB9204008FA782 /* Debug */ = {
711 | isa = XCBuildConfiguration;
712 | baseConfigurationReference = 56FDD6DA44AC86C2E1654D1A /* Pods-SwiftyMock_Tests.debug.xcconfig */;
713 | buildSettings = {
714 | FRAMEWORK_SEARCH_PATHS = (
715 | "$(SDKROOT)/Developer/Library/Frameworks",
716 | "$(inherited)",
717 | );
718 | GCC_PREPROCESSOR_DEFINITIONS = (
719 | "DEBUG=1",
720 | "$(inherited)",
721 | );
722 | INFOPLIST_FILE = Tests/Info.plist;
723 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
724 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
725 | PRODUCT_NAME = "$(TARGET_NAME)";
726 | SWIFT_VERSION = 4.0;
727 | };
728 | name = Debug;
729 | };
730 | 607FACF41AFB9204008FA782 /* Release */ = {
731 | isa = XCBuildConfiguration;
732 | baseConfigurationReference = F8922BE058C4D4604D03C886 /* Pods-SwiftyMock_Tests.release.xcconfig */;
733 | buildSettings = {
734 | FRAMEWORK_SEARCH_PATHS = (
735 | "$(SDKROOT)/Developer/Library/Frameworks",
736 | "$(inherited)",
737 | );
738 | INFOPLIST_FILE = Tests/Info.plist;
739 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
740 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
741 | PRODUCT_NAME = "$(TARGET_NAME)";
742 | SWIFT_VERSION = 4.0;
743 | };
744 | name = Release;
745 | };
746 | E481D68B1D4DDDBE000E73AE /* Debug */ = {
747 | isa = XCBuildConfiguration;
748 | baseConfigurationReference = 780C71DD02D492D34BF6DC2F /* Pods-RoboKittenTests.debug.xcconfig */;
749 | buildSettings = {
750 | BUNDLE_LOADER = "$(TEST_HOST)";
751 | CLANG_ANALYZER_NONNULL = YES;
752 | DEBUG_INFORMATION_FORMAT = dwarf;
753 | INFOPLIST_FILE = RoboKittenTests/Info.plist;
754 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
755 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
756 | PRODUCT_BUNDLE_IDENTIFIER = com.stanfy.RoboKittenTests;
757 | PRODUCT_NAME = "$(TARGET_NAME)";
758 | SWIFT_VERSION = 4.0;
759 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SwiftyMock_Example.app/SwiftyMock_Example";
760 | };
761 | name = Debug;
762 | };
763 | E481D68C1D4DDDBE000E73AE /* Release */ = {
764 | isa = XCBuildConfiguration;
765 | baseConfigurationReference = E6DD82C8225916729797ED83 /* Pods-RoboKittenTests.release.xcconfig */;
766 | buildSettings = {
767 | BUNDLE_LOADER = "$(TEST_HOST)";
768 | CLANG_ANALYZER_NONNULL = YES;
769 | INFOPLIST_FILE = RoboKittenTests/Info.plist;
770 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
771 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
772 | PRODUCT_BUNDLE_IDENTIFIER = com.stanfy.RoboKittenTests;
773 | PRODUCT_NAME = "$(TARGET_NAME)";
774 | SWIFT_VERSION = 4.0;
775 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SwiftyMock_Example.app/SwiftyMock_Example";
776 | };
777 | name = Release;
778 | };
779 | /* End XCBuildConfiguration section */
780 |
781 | /* Begin XCConfigurationList section */
782 | 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "SwiftyMock" */ = {
783 | isa = XCConfigurationList;
784 | buildConfigurations = (
785 | 607FACED1AFB9204008FA782 /* Debug */,
786 | 607FACEE1AFB9204008FA782 /* Release */,
787 | );
788 | defaultConfigurationIsVisible = 0;
789 | defaultConfigurationName = Release;
790 | };
791 | 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "SwiftyMock_Example" */ = {
792 | isa = XCConfigurationList;
793 | buildConfigurations = (
794 | 607FACF01AFB9204008FA782 /* Debug */,
795 | 607FACF11AFB9204008FA782 /* Release */,
796 | );
797 | defaultConfigurationIsVisible = 0;
798 | defaultConfigurationName = Release;
799 | };
800 | 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "SwiftyMock_Tests" */ = {
801 | isa = XCConfigurationList;
802 | buildConfigurations = (
803 | 607FACF31AFB9204008FA782 /* Debug */,
804 | 607FACF41AFB9204008FA782 /* Release */,
805 | );
806 | defaultConfigurationIsVisible = 0;
807 | defaultConfigurationName = Release;
808 | };
809 | E481D68A1D4DDDBE000E73AE /* Build configuration list for PBXNativeTarget "RoboKittenTests" */ = {
810 | isa = XCConfigurationList;
811 | buildConfigurations = (
812 | E481D68B1D4DDDBE000E73AE /* Debug */,
813 | E481D68C1D4DDDBE000E73AE /* Release */,
814 | );
815 | defaultConfigurationIsVisible = 0;
816 | defaultConfigurationName = Release;
817 | };
818 | /* End XCConfigurationList section */
819 | };
820 | rootObject = 607FACC81AFB9204008FA782 /* Project object */;
821 | }
822 |
--------------------------------------------------------------------------------
/Example/SwiftyMock.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/SwiftyMock.xcodeproj/xcshareddata/xcschemes/SwiftyMock-Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
57 |
63 |
64 |
65 |
66 |
67 |
73 |
74 |
75 |
76 |
77 |
78 |
88 |
90 |
96 |
97 |
98 |
99 |
100 |
101 |
107 |
109 |
115 |
116 |
117 |
118 |
120 |
121 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/Example/SwiftyMock.xcodeproj/xcshareddata/xcschemes/SwiftyMock-Tests.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
55 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
74 |
76 |
77 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/Example/SwiftyMock.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/SwiftyMock/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // SwiftyMock
4 | //
5 | // Created by Paul Taykalo on 07/29/2016.
6 | // Copyright (c) 2016 Paul Taykalo. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/Example/SwiftyMock/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Example/SwiftyMock/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Example/SwiftyMock/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Example/SwiftyMock/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Example/SwiftyMock/RoboKitten/Implementations/RoboKittenV1.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Paul Taykalo on 7/31/16.
3 | // Copyright (c) 2016 CocoaPods. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | class RoboKittenV1: RoboKitten {
9 |
10 | func batteryStatus() -> Int {
11 | return 0
12 | }
13 |
14 | func jump(x: Int, y: Int) {
15 | }
16 |
17 | func canJumpAt(x: Int, y: Int) -> Bool {
18 | return false
19 | }
20 |
21 | func rest(_ completed: @escaping (Bool) -> ()) {
22 |
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Example/SwiftyMock/RoboKitten/RoboKitten.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Paul Taykalo on 7/31/16.
3 | // Copyright (c) 2016 CocoaPods. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | // sourcery: Mock
9 | protocol RoboKitten {
10 | @discardableResult func batteryStatus() -> Int
11 | func jump(x: Int, y: Int)
12 | @discardableResult func canJumpAt(x: Int, y: Int) -> Bool
13 | func rest(_ completed: @escaping (Bool) -> ())
14 | }
15 |
16 | // sourcery: Mock
17 | protocol LazyRoboKitten: RoboKitten {
18 | var needsRest: Bool { get set }
19 | }
--------------------------------------------------------------------------------
/Example/SwiftyMock/RoboKitten/RoboKittenController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Paul Taykalo on 7/31/16.
3 | // Copyright (c) 2016 CocoaPods. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | enum BatteyStatus: Equatable {
9 | case low
10 | case normal
11 | case full
12 | }
13 |
14 | enum Result {
15 | case success
16 | case failure
17 | }
18 |
19 |
20 | class RoboKittenController {
21 | let kitten: RoboKitten
22 |
23 | init(kitten: RoboKitten) {
24 | self.kitten = kitten
25 | }
26 |
27 | @discardableResult func batteryStatus() -> BatteyStatus {
28 | if kitten.batteryStatus() >= 100 {
29 | return .full
30 | }
31 | if (kitten.batteryStatus() < 10) {
32 | return .low
33 | }
34 | return .normal
35 | }
36 |
37 | @discardableResult func jumpAt(x: Int, y: Int) -> Result {
38 | if kitten.canJumpAt(x: x, y: y) {
39 | kitten.jump(x: x, y: y)
40 | return .success
41 | }
42 | return .failure
43 | }
44 |
45 | @discardableResult func jump(inSequence sequence: [(x: Int, y: Int)]) -> Result {
46 | for coords in sequence {
47 | if !kitten.canJumpAt(x: coords.x, y: coords.y) {
48 | return .failure
49 | }
50 | }
51 | for coords in sequence {
52 | kitten.jump(x: coords.x, y: coords.y)
53 | }
54 | return .success
55 | }
56 |
57 | func rest(_ completion: @escaping (Result) -> ()) {
58 | kitten.rest { successfuly in
59 | switch successfuly {
60 | case true: completion(.success)
61 | case false: completion(.failure)
62 | }
63 | }
64 | }
65 |
66 | }
67 |
68 |
--------------------------------------------------------------------------------
/Example/SwiftyMock/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // SwiftyMock
4 | //
5 | // Created by Paul Taykalo on 07/29/2016.
6 | // Copyright (c) 2016 Paul Taykalo. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController {
12 |
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/Example/Tests/Calls/ReactiveMatchers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ReactiveMatchers.swift
3 | // SwiftyMock_Example
4 | //
5 | // Created by Alexander Voronov on 11/23/17.
6 | // Copyright © 2017 CocoaPods. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import Quick
11 | import Nimble
12 | import Result
13 | import ReactiveSwift
14 |
15 | // MARK: - Send Value
16 |
17 | private func sendValue(
18 | where predicate: @escaping (V) -> Bool,
19 | expectation: @escaping (Signal.Event?, V?) -> ExpectationMessage
20 | ) -> Predicate where T.Value == V, T.Error == E {
21 | return Predicate { (actualExpression: Expression) throws -> PredicateResult in
22 | var actualEvent: Signal.Event?
23 | var actualValue: V?
24 | var satisfies: Bool = false
25 | let actualProducer = try actualExpression.evaluate()
26 | actualProducer?.producer.start { event in
27 | actualEvent = event
28 | if case let .value(value) = event {
29 | actualValue = value
30 | satisfies = predicate(value)
31 | }
32 | }
33 | guard actualValue != nil else {
34 | return PredicateResult(
35 | status: .fail,
36 | message: expectation(actualEvent, actualValue)
37 | )
38 | }
39 | return PredicateResult(
40 | bool: satisfies,
41 | message: expectation(actualEvent, actualValue)
42 | )
43 | }
44 | }
45 |
46 | func sendValue(where predicate: @escaping (V) -> Bool) -> Predicate where T.Value == V {
47 | return sendValue(where: predicate, expectation: { (actualEvent, actualValue) in
48 | .expectedCustomValueTo(
49 | "send value to satisfy predicate",
50 | message(forEvent: actualEvent, value: actualValue)
51 | )
52 | })
53 | }
54 |
55 | func sendValue(_ expectedValue: V) -> Predicate where T.Value == V {
56 | return sendValue(where: { $0 == expectedValue }, expectation: { (actualEvent, actualValue) in
57 | .expectedCustomValueTo(
58 | "send value <\(stringify(expectedValue))>",
59 | message(forEvent: actualEvent, value: actualValue)
60 | )
61 | })
62 | }
63 |
64 | func sendEmptyValue() -> Predicate where T.Value == Void {
65 | return sendValue(where: { true }, expectation: { (actualEvent, actualValue) in
66 | .expectedCustomValueTo(
67 | "send value ",
68 | message(forEvent: actualEvent, value: actualValue)
69 | )
70 | })
71 | }
72 |
73 | // MARK: - Send Value and Complete
74 |
75 | private func sendValueAndComplete(
76 | where predicate: @escaping (V) -> Bool,
77 | expectation: @escaping (Signal.Event?, V?) -> ExpectationMessage
78 | ) -> Predicate where T.Value == V, T.Error == E {
79 | return Predicate { (actualExpression: Expression) throws -> PredicateResult in
80 | var actualEvent: Signal.Event?
81 | var completed: Bool = false
82 | var actualValue: V?
83 | var satisfies: Bool = false
84 | let actualProducer = try actualExpression.evaluate()
85 | actualProducer?.producer.start { event in
86 | actualEvent = event
87 | if case let .value(value) = event {
88 | actualValue = value
89 | satisfies = predicate(value)
90 | }
91 | if case .completed = event {
92 | completed = true
93 | } else {
94 | completed = false
95 | }
96 | }
97 | guard actualValue != nil, completed else {
98 | return PredicateResult(
99 | status: .fail,
100 | message: expectation(actualEvent, actualValue)
101 | )
102 | }
103 | return PredicateResult(
104 | bool: satisfies,
105 | message: expectation(actualEvent, actualValue)
106 | )
107 | }
108 | }
109 |
110 | func sendValueAndComplete(where predicate: @escaping (V) -> Bool) -> Predicate where T.Value == V {
111 | return sendValueAndComplete(where: predicate, expectation: { (actualEvent, actualValue) in
112 | .expectedCustomValueTo(
113 | "send value to satisfy predicate and complete",
114 | message(forEvent: actualEvent, value: actualValue)
115 | )
116 | })
117 | }
118 |
119 | func sendValueAndComplete(_ expectedValue: V) -> Predicate where T.Value == V {
120 | return sendValue(where: { $0 == expectedValue }, expectation: { (actualEvent, actualValue) in
121 | .expectedCustomValueTo(
122 | "send value <\(stringify(expectedValue))> and complete",
123 | message(forEvent: actualEvent, value: actualValue)
124 | )
125 | })
126 | }
127 |
128 | func sendEmptyValueAndComplete() -> Predicate where T.Value == Void {
129 | return sendValue(where: { true }, expectation: { (actualEvent, actualValue) in
130 | .expectedCustomValueTo(
131 | "send value and complete",
132 | message(forEvent: actualEvent, value: actualValue)
133 | )
134 | })
135 | }
136 |
137 | // MARK: - Complete
138 |
139 | func complete() -> Predicate where T.Value == V, T.Error == E {
140 | return Predicate { (actualExpression: Expression) throws -> PredicateResult in
141 | var actualEvent: Signal.Event?
142 | var completed: Bool = false
143 | let actualProducer = try actualExpression.evaluate()
144 | actualProducer?.producer.start { event in
145 | actualEvent = event
146 | if case .completed = event {
147 | completed = true
148 | }
149 | }
150 | return PredicateResult(
151 | bool: completed,
152 | message: .expectedCustomValueTo("complete", message(forEvent: actualEvent))
153 | )
154 | }
155 | }
156 |
157 | // MARK: - Fail
158 |
159 | private func fail(
160 | where predicate: @escaping (E) -> Bool,
161 | expectation: @escaping (Signal.Event?, E?) -> ExpectationMessage
162 | ) -> Predicate where T.Value == V, T.Error == E {
163 | return Predicate { (actualExpression: Expression) throws -> PredicateResult in
164 | var actualEvent: Signal.Event?
165 | var actualError: E?
166 | var matches: Bool = false
167 | let actualProducer = try actualExpression.evaluate()
168 | actualProducer?.producer.start { event in
169 | actualEvent = event
170 | if case let .failed(error) = event {
171 | actualError = error
172 | matches = predicate(error)
173 | }
174 | }
175 | guard actualError != nil else {
176 | return PredicateResult(
177 | status: .fail,
178 | message: expectation(actualEvent, actualError)
179 | )
180 | }
181 | return PredicateResult(
182 | bool: matches,
183 | message: expectation(actualEvent, actualError)
184 | )
185 | }
186 | }
187 |
188 | func fail(where predicate: @escaping (E) -> Bool) -> Predicate where T.Error == E {
189 | return fail(where: predicate, expectation: { (actualEvent, actualError) in
190 | .expectedCustomValueTo(
191 | "send error to satisfy predicate",
192 | message(forEvent: actualEvent, error: actualError)
193 | )
194 | })
195 | }
196 |
197 | func fail(with expectedError: E) -> Predicate where T.Error == E {
198 | return fail(where: { errorMatchesExpectedError($0, expectedError: expectedError) }, expectation: { (actualEvent, actualError) in
199 | .expectedCustomValueTo(
200 | "send error <\(stringify(expectedError))>",
201 | message(forEvent: actualEvent, error: actualError)
202 | )
203 | })
204 | }
205 |
206 | func fail(with expectedError: E) -> Predicate where T.Error == E {
207 | return fail(where: { $0 == expectedError }, expectation: { (actualEvent, actualError) in
208 | .expectedCustomValueTo(
209 | "send error <\(stringify(expectedError))>",
210 | message(forEvent: actualEvent, error: actualError)
211 | )
212 | })
213 | }
214 |
215 | func failWithNoError() -> Predicate where T.Error == NoError {
216 | return fail(where: { _ in true }, expectation: { (actualEvent, actualError) in
217 | .expectedCustomValueTo(
218 | "send error ",
219 | message(forEvent: actualEvent, error: actualError)
220 | )
221 | })
222 | }
223 |
224 | // MARK: - Interrupt
225 |
226 | func interrupt() -> Predicate where T.Value == V, T.Error == E {
227 | return Predicate { (actualExpression: Expression) throws -> PredicateResult in
228 | var actualEvent: Signal.Event?
229 | var interrupted: Bool = false
230 | let actualProducer = try actualExpression.evaluate()
231 | actualProducer?.producer.start { event in
232 | actualEvent = event
233 | if case .interrupted = event {
234 | interrupted = true
235 | }
236 | }
237 | return PredicateResult(
238 | bool: interrupted,
239 | message: .expectedCustomValueTo("interrupt", message(forEvent: actualEvent))
240 | )
241 | }
242 | }
243 |
244 | // MARK: - Helpers
245 |
246 | private func errorMatchesExpectedError(_ actualError: Error, expectedError: T) -> Bool {
247 | return actualError._domain == expectedError._domain
248 | && actualError._code == expectedError._code
249 | }
250 |
251 | private func message(forEvent event: Signal.Event?) -> String {
252 | if let event = event {
253 | return "<\(stringify(event))> event"
254 | }
255 | return "no event"
256 | }
257 |
258 | private func message(forEvent event: Signal.Event?, value: V?) -> String {
259 | if let event = event {
260 | if case .value = event {
261 | return "<\(stringify(value))> value"
262 | }
263 | return "<\(stringify(event))> event with <\(stringify(value))> value"
264 | }
265 | return "no event"
266 | }
267 |
268 | private func message(forEvent event: Signal.Event?, error: E?) -> String {
269 | if let event = event {
270 | if case .failed = event {
271 | return "<\(stringify(error))> error"
272 | }
273 | return "<\(stringify(event))> event with <\(stringify(error))> error"
274 | }
275 | return "no event"
276 | }
277 |
--------------------------------------------------------------------------------
/Example/Tests/Calls/SwiftyMockCallsSpec.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftyMockCallsSpec.swift
3 | // SwiftyMock
4 | //
5 | // Created by Paul Taykalo on 7/29/16.
6 | // Copyright © 2016 CocoaPods. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import Quick
11 | import Nimble
12 | @testable import SwiftyMock
13 |
14 | protocol Calculator {
15 | func sum(left: Int, right: Int) -> Int
16 | }
17 |
18 | class TestCalculator: Calculator {
19 | let sum = FunctionCall<(left: Int, right: Int), Int>()
20 | @discardableResult func sum(left: Int, right: Int) -> Int {
21 | return stubCall(sum, argument: (left: left, right: right))
22 | }
23 | }
24 |
25 | class SwiftyMockCallsSpec: QuickSpec {
26 | override func spec() {
27 | describe("SwiftyMockCalls") {
28 | describe("when correctly setup") {
29 | var sut: TestCalculator!
30 | beforeEach {
31 | sut = TestCalculator()
32 | }
33 |
34 | context("before calling stubbed method") {
35 | it("should tell that method wasnt' called") {
36 | expect(sut.sum.called).to(beFalsy())
37 | }
38 | it("should have calls count equal to zero") {
39 | expect(sut.sum.callsCount).to(equal(0))
40 | }
41 | it("should not have captured argumen") {
42 | expect(sut.sum.capturedArgument).to(beNil())
43 | }
44 |
45 | it("should not have captured argumens") {
46 | expect(sut.sum.capturedArguments).to(beEmpty())
47 | }
48 |
49 | }
50 | context("when calling method before stubbing") {
51 | it("should fail with assertion") {
52 | expect { sut.sum(left: 1,right: 2) }.to(throwAssertion())
53 | }
54 | }
55 | context("when calling stubbed method") {
56 | context("with value stub") {
57 | beforeEach {
58 | sut.sum.returns(12)
59 | }
60 | it("should return stubbed value") {
61 | expect(sut.sum(left: 1,right:2)).to(equal(12))
62 | }
63 | it("should have calls count equal number of calls") {
64 | sut.sum(left: 1,right:2)
65 | expect(sut.sum.callsCount).to(equal(1))
66 |
67 | sut.sum(left: 2,right:3)
68 | sut.sum(left: 3,right:5)
69 | expect(sut.sum.callsCount).to(equal(3))
70 | }
71 |
72 | it("tell that method was called") {
73 | sut.sum(left: 1,right:2)
74 | expect(sut.sum.called).to(beTruthy())
75 | }
76 | }
77 | context("with logic stub") {
78 | beforeEach {
79 | sut.sum.performs { $0.left - $0.right }
80 | }
81 | it("should calculate method based on the stubbed block") {
82 | expect(sut.sum(left: 1, right:2)).to(equal(-1))
83 | expect(sut.sum(left: 3, right:2)).to(equal(1))
84 | }
85 | it("should have calls count equal number of calls") {
86 | sut.sum(left: 1,right:2)
87 | expect(sut.sum.callsCount).to(equal(1))
88 |
89 | sut.sum(left: 2,right:3)
90 | sut.sum(left: 3,right:5)
91 | expect(sut.sum.callsCount).to(equal(3))
92 | }
93 | it("should tell that method was called") {
94 | sut.sum(left: 1,right:2)
95 | expect(sut.sum.called).to(beTruthy())
96 | }
97 | }
98 | context("with logic and value stub") {
99 | beforeEach {
100 | sut.sum.returns(12)
101 | sut.sum.performs { $0.left + $0.right}
102 | }
103 | it("should use logic stub instead of value") {
104 | expect(sut.sum(left: 15, right:12)).to(equal(27))
105 | }
106 | }
107 | }
108 |
109 | context("when calling filtered value stubbed method") {
110 | beforeEach {
111 | sut.sum.returns(10)
112 | sut.sum.on { $0.left == 12 }.returns(0)
113 | sut.sum.on { $0.right == 15 }.returns(7)
114 | }
115 | context("when parameters matching filter") {
116 | it("should return filter srubbed value") {
117 | expect(sut.sum(left: 12,right:2)).to(equal(0))
118 | expect(sut.sum(left: 0,right:15)).to(equal(7))
119 | }
120 | }
121 | context("when parameters doesn't match filters") {
122 | it("should return default stubbed value") {
123 | expect(sut.sum(left: 13,right:2)).to(equal(10))
124 | }
125 | }
126 | }
127 |
128 | context("when calling filtered block stubbed method") {
129 | beforeEach {
130 | sut.sum.performs { $0.left + $0.right }
131 | sut.sum.on { $0.left == 0 }.performs { _ in 0 }
132 | sut.sum.on { $0.right == 0 }.performs { _ in 12 }
133 | }
134 | context("when parameters matching filter") {
135 | it("should return call filter-based block") {
136 | expect(sut.sum(left: 0,right:2)).to(equal(0))
137 | expect(sut.sum(left: 15,right:0)).to(equal(12))
138 | }
139 | }
140 | context("when parameters doesn't match filters") {
141 | it("should return call default stubbed block") {
142 | expect(sut.sum(left: 13,right:2)).to(equal(15))
143 | }
144 | }
145 | }
146 |
147 |
148 | context("when calling filtered stubbed with block method") {
149 | beforeEach {
150 | sut.sum.returns(17)
151 | sut.sum.on { $0.left == 12 }.performs { $0.left + $0.right }
152 | }
153 | context("when parameters matching filter") {
154 | it("should return calculated with stub value") {
155 | expect(sut.sum(left: 12,right:2)).to(equal(14))
156 | expect(sut.sum(left: 12,right:12)).to(equal(24))
157 | }
158 | }
159 | context("when parameters doesn't match filters") {
160 | it("should return default stubbed value") {
161 | expect(sut.sum(left: 13,right:2)).to(equal(17))
162 | }
163 | }
164 | }
165 | }
166 | }
167 | }
168 | }
169 |
170 |
--------------------------------------------------------------------------------
/Example/Tests/Calls/SwiftyMockReactiveCallsSpec.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftyMockReactiveCallsSpec.swift
3 | // SwiftyMock_Example
4 | //
5 | // Created by Alexander Voronov on 11/23/17.
6 | // Copyright © 2017 CocoaPods. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import Quick
11 | import Nimble
12 | import ReactiveSwift
13 | import Result
14 | @testable import SwiftyMock
15 |
16 | protocol ReactiveCalculator {
17 | func sum(left: Int, right: Int) -> SignalProducer
18 | }
19 |
20 | class TestReactiveCalculator: ReactiveCalculator {
21 | init() {}
22 |
23 | let sum = ReactiveCall<(left: Int, right: Int), Int, TestError>()
24 | @discardableResult func sum(left: Int, right: Int) -> SignalProducer {
25 | return stubCall(sum, argument: (left: left, right: right))
26 | }
27 | }
28 |
29 | struct TestError: Error, Equatable {
30 | let id: Int
31 | init() { id = 0 }
32 | init(id: Int) { self.id = id }
33 | }
34 |
35 | class SwiftyMockReactiveCallsSpec: QuickSpec {
36 | override func spec() {
37 | describe("SwiftyMockReactiveCalls") {
38 | describe("when correctly setup") {
39 | var sut: TestReactiveCalculator!
40 | beforeEach {
41 | sut = TestReactiveCalculator()
42 | }
43 |
44 | context("before calling stubbed method") {
45 | it("should tell that method wasn't called") {
46 | expect(sut.sum.called).to(beFalsy())
47 | }
48 | it("should have calls count equal to zero") {
49 | expect(sut.sum.callsCount).to(equal(0))
50 | }
51 | it("should not have captured argument") {
52 | expect(sut.sum.capturedArgument).to(beNil())
53 | }
54 | it("should not have captured arguments") {
55 | expect(sut.sum.capturedArguments).to(beEmpty())
56 | }
57 | }
58 |
59 | context("when calling method before stubbing") {
60 | fit("should return empty signal without any value") {
61 | expect { sut.sum(left: 1,right: 2) }.to(complete())
62 | }
63 | }
64 |
65 | context("when calling stubbed method") {
66 | context("with value stub") {
67 | beforeEach {
68 | sut.sum.returns(.success(12))
69 | }
70 |
71 | it("should return stubbed value and complete") {
72 | let result = sut.sum(left: 1, right: 2)
73 | expect(result).to(sendValue(12))
74 | expect(result).to(complete())
75 | }
76 |
77 | it("should have calls count equal number of calls") {
78 | sut.sum(left: 1, right: 2)
79 | expect(sut.sum.callsCount).to(equal(1))
80 |
81 | sut.sum(left: 2, right: 3)
82 | sut.sum(left: 3, right: 5)
83 | expect(sut.sum.callsCount).to(equal(3))
84 | }
85 |
86 | it("should tell that method was called") {
87 | sut.sum(left: 1,right: 2)
88 | expect(sut.sum.called).to(beTruthy())
89 | }
90 | }
91 |
92 | context("with failure value stub") {
93 | beforeEach {
94 | sut.sum.returns(.failure(TestError()))
95 | }
96 |
97 | it("should return stubbed error") {
98 | expect(sut.sum(left: 1, right: 2)).to(fail(with: TestError()))
99 | }
100 | }
101 |
102 | context("with logic stub") {
103 | beforeEach {
104 | sut.sum.performs { .success($0.left - $0.right) }
105 | }
106 |
107 | it("should calculate method based on the stubbed block") {
108 | expect(sut.sum(left: 1, right: 2)).to(sendValue(-1))
109 | expect(sut.sum(left: 3, right: 2)).to(sendValue(1))
110 | }
111 |
112 | it("should have calls count equal number of calls") {
113 | sut.sum(left: 1, right: 2)
114 | expect(sut.sum.callsCount).to(equal(1))
115 |
116 | sut.sum(left: 2, right: 3)
117 | sut.sum(left: 3, right: 5)
118 | expect(sut.sum.callsCount).to(equal(3))
119 | }
120 |
121 | it("tell that method was called") {
122 | sut.sum(left: 1, right:2)
123 | expect(sut.sum.called).to(beTruthy())
124 | }
125 | }
126 |
127 | context("with failure logic stub") {
128 | beforeEach {
129 | sut.sum.performs { _ in .failure(TestError()) }
130 | }
131 |
132 | it("should return stubbed error") {
133 | expect(sut.sum(left: 1, right: 2)).to(fail(with: TestError()))
134 | }
135 | }
136 |
137 | context("with value and logic stub") {
138 | beforeEach {
139 | sut.sum.returns(.success(12))
140 | sut.sum.performs { .success($0.left + $0.right) }
141 | }
142 |
143 | it("should use logic stub instead of value") {
144 | expect(sut.sum(left: 15, right: 12)).to(sendValue(27))
145 | }
146 | }
147 |
148 | context("with value and failure logic stub") {
149 | beforeEach {
150 | sut.sum.returns(.success(12))
151 | sut.sum.performs { _ in .failure(TestError()) }
152 | }
153 |
154 | it("should use failure logic stub instead of value") {
155 | expect(sut.sum(left: 15, right: 12)).to(fail(with: TestError()))
156 | }
157 | }
158 |
159 | context("with failure value and logic stub") {
160 | beforeEach {
161 | sut.sum.returns(.failure(TestError()))
162 | sut.sum.performs { .success($0.left + $0.right) }
163 | }
164 |
165 | it("should use logic stub instead of failure value") {
166 | expect(sut.sum(left: 15, right: 12)).to(sendValue(27))
167 | }
168 | }
169 |
170 | context("with failure value and failure logic stub") {
171 | beforeEach {
172 | sut.sum.returns(.failure(TestError(id: 0)))
173 | sut.sum.performs { _ in .failure(TestError(id: 1)) }
174 | }
175 |
176 | it("should use failure logic stub instead of failure value") {
177 | expect(sut.sum(left: 15, right: 12)).to(fail(with: TestError(id: 1)))
178 | }
179 | }
180 | }
181 |
182 | context("when calling filtered value stubbed method") {
183 | beforeEach {
184 | sut.sum.returns(.success(10))
185 | sut.sum.on { $0.left == 12 }.returns(.success(0))
186 | sut.sum.on { $0.right == 15 }.returns(.success(7))
187 | sut.sum.on { $0.right == 42 }.returns(.failure(TestError()))
188 | }
189 | context("when parameters matching filter") {
190 | it("should return filter srubbed value") {
191 | expect(sut.sum(left: 12, right: 2)).to(sendValue(0))
192 | expect(sut.sum(left: 0, right: 15)).to(sendValue(7))
193 | expect(sut.sum(left: 23, right: 42)).to(fail(with: TestError()))
194 | }
195 | }
196 | context("when parameters don't match filters") {
197 | it("should return default stubbed value") {
198 | expect(sut.sum(left: 13, right: 2)).to(sendValue(10))
199 | }
200 | }
201 | }
202 |
203 | context("when calling filtered block stubbed method") {
204 | beforeEach {
205 | sut.sum.performs { .success($0.left - $0.right) }
206 | sut.sum.on { $0.left == 0 }.performs { _ in .success(0) }
207 | sut.sum.on { $0.right == 0 }.performs { _ in .success(12) }
208 | sut.sum.on { $0.right == -1 }.performs { _ in .failure(TestError()) }
209 | }
210 | context("when parameters matching filter") {
211 | it("should return call filter-based block") {
212 | expect(sut.sum(left: 0, right: 2)).to(sendValue(0))
213 | expect(sut.sum(left: 15, right: 0)).to(sendValue(12))
214 | expect(sut.sum(left: 15, right: -1)).to(fail(with: TestError()))
215 | }
216 | }
217 | context("when parameters don't match filters") {
218 | it("should call default stubbed block") {
219 | expect(sut.sum(left: 13, right: 2)).to(sendValue(11))
220 | }
221 | }
222 | }
223 |
224 | context("when calling filtered stubbed with block method") {
225 | beforeEach {
226 | sut.sum.returns(.success(17))
227 | sut.sum.on { $0.left == 12 }.performs { .success($0.left - $0.right) }
228 | sut.sum.on { $0.right == 42 }.performs { _ in .failure(TestError()) }
229 | }
230 | context("when parameters matching filter") {
231 | it("should return calculated with stub value") {
232 | expect(sut.sum(left: 12, right: 2)).to(sendValue(10))
233 | expect(sut.sum(left: 12, right: 12)).to(sendValue(0))
234 | expect(sut.sum(left: 42, right: 12)).to(fail(with: TestError()))
235 | }
236 | }
237 | context("when parameters don't match filters") {
238 | it("should return default stubbed value") {
239 | expect(sut.sum(left: 13, right: 2)).to(sendValue(17))
240 | }
241 | }
242 | }
243 | }
244 | }
245 | }
246 | }
247 |
--------------------------------------------------------------------------------
/Example/Tests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 Stanfy
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SwiftyMock [](https://travis-ci.org/stanfy/SwiftyMock)
2 |
3 | This repository contains helpers that make mocking, stubbing and spying in Swift much easier
4 |
5 | # Example
6 |
7 | ## Protocol
8 | Imagine you have some protocol that describes some behaviour
9 |
10 | ```swift
11 | protocol RoboKitten {
12 | func batteryStatus() -> Int
13 | func jump(x x: Int, y: Int) -> Int
14 | func canJumpAt(x x: Int, y: Int) -> Bool
15 | func rest(completed: Bool -> () )
16 | }
17 | ```
18 |
19 | ## Protocol usage
20 | And this protocol is used somewhere
21 |
22 | ```swift
23 | class RoboKittenController {
24 | let kitten: RoboKitten
25 |
26 | init(kitten: RoboKitten) {
27 | self.kitten = kitten
28 | }
29 |
30 | func jumpAt(x x: Int, y: Int) -> Result {
31 | if kitten.canJumpAt(x: x, y: y) {
32 | kitten.jump(x: x, y: y)
33 | return .SUCCESS
34 | }
35 | return .FAILURE
36 | }
37 | ...
38 | }
39 | ```
40 | ## Protocol mock
41 |
42 | So now you want to test how protocol is used as a dependency
43 | And you create to create mock implementation of protocol
44 | And create fake calls for each method you want to test
45 | So here how it will look like in SwiftyMock
46 |
47 | ```swift
48 | class RoboKittenMock: RoboKitten {
49 |
50 | let batteryStatusCall = FunctionCall<(), Int>()
51 | func batteryStatus() -> Int {
52 | return stubCall(batteryStatusCall, argument:())
53 | }
54 |
55 | let jumpCall = FunctionCall<(x: Int, y: Int), Int>()
56 | func jump(x x: Int, y: Int) -> Int {
57 | return stubCall(jumpCall, argument: (x: x, y: y))
58 | }
59 |
60 | let canJumpAtCall = FunctionCall<(x: Int, y: Int), Bool>()
61 | func canJumpAt(x x: Int, y: Int) -> Bool {
62 | return stubCall(canJumpAtCall, argument: (x: x, y: y))
63 | }
64 |
65 | let restCall = FunctionCall (), ()>()
66 | func rest(completed: Bool -> ()) {
67 | return stubCall(restCall, argument: completed, defaultValue: ())
68 | }
69 | }
70 | ```
71 |
72 | ## Mock usage
73 | If setup was correct it's really easy to specify mock behaviour by using subbed methods
74 |
75 | ### Method stub
76 | Let's say we want to our mock to return some values
77 | It's really easy
78 | ```swift
79 | // like this
80 | kittenMock.canJumpAtCall.returns(false)
81 |
82 | // or like this
83 | kittenMock.jumpCall.returns(20)
84 | ```
85 |
86 | Sometimes, you have bit more complex rules when and what to return
87 | ```swift
88 | // You can add as many filters you like
89 | // More specific rules overrides general rules
90 | kittenMock.canJumpAtCall
91 | .on { $0.x < 0 }.returns(false)
92 | .on { $0.y < 0 }.returns(false)
93 | .returns(true) // in all other cases
94 |
95 | ```
96 |
97 | And sometimes you need even more complex mock behaviour, when you need for example to pass closures into mock
98 | ```swift
99 | protocol RoboKitten {
100 | func rest(completed: Bool -> () )
101 | }
102 |
103 | kittenMock.restCall.performs { completion in
104 | print("Mock method was called! Remove this in prod version:))")
105 | completion(true)
106 | }
107 | ```
108 |
109 | ### Method call check
110 | Also from time to time, you need to be sure that method was called
111 | ```swift
112 | beforeEach {
113 | // Since canjump method need to return somtehing we need to specify return value
114 | kittenMock.canJumpAtCall.returns(false)
115 | }
116 | it("should ask kitten if it's available to jump there") {
117 | sut.jumpAt(x: 10, y: 20)
118 | expect(kittenMock.canJumpAtCall.called).to(beTruthy())
119 | }
120 | ```
121 |
122 | Or you need to check that method was called exact number of times
123 | ```swift
124 | it("should actually ask kitten to jump only once per call") {
125 | sut.jumpAt(x: 18, y: 23)
126 | expect(kittenMock.jumpCall.callsCount).to(equal(1))
127 |
128 | sut.jumpAt(x: 80, y: 15)
129 | expect(kittenMock.jumpCall.callsCount).to(equal(2))
130 | }
131 | ```
132 |
133 | All method calls are stored in the mock, so you can easily check if mock was called with correct parameters
134 | ```swift
135 | it("should ask kitten if it's available to jump there with the same coords") {
136 | sut.jumpAt(x: 10, y: 20)
137 | expect(kittenMock.canJumpAtCall.capturedArgument?.x).to(equal(10))
138 | expect(kittenMock.canJumpAtCall.capturedArgument?.y).to(equal(20))
139 | }
140 | ```
141 |
142 | ## [ReactiveSwift](https://github.com/ReactiveCocoa/ReactiveSwift) stubs support
143 | API for methods that return `SignalProducer` or `Action` is pretty much the same as for usual methods stubs.
144 |
145 | Imagine RoboKitten protocol is a bit changed and returns SignalProducer instead of plain value, so we can keep and eye on battery status level.
146 |
147 | ```swift
148 | protocol RoboKitten {
149 | func batteryStatus() -> SignalProducer
150 | }
151 | ```
152 |
153 | Now you create mock implementation of this protocol, but instead of `FunctionCall`, you're using `ReactiveCall`.
154 | The only difference is that we've added third type constraint to specify `Error`.
155 |
156 | ```swift
157 | class RoboKittenMock: RoboKitten {
158 | let batteryStatusCall = ReactiveCall<(), Int, NoError>()
159 | func batteryStatus() -> SignalProducer {
160 | return stubCall(batteryStatusCall, argument:())
161 | }
162 | }
163 | ```
164 |
165 | ### Method stub
166 | Since `SignalProducer` is constrained by **Value** and **Error** types, we need to allow user to choose, which one to stub call with.
167 | Luckily there's handy [Result](https://github.com/antitypical/Result) type and its implementation comes along with [ReactiveSwift](https://github.com/ReactiveCocoa/ReactiveSwift).
168 | Thus in order to stub `ReactiveCall`, you use `Result` instead of plain value as you did with `FunctionCall`.
169 |
170 | ```swift
171 | // like this
172 | kittenMock.batteryStatusCall.returns(.success(42))
173 | // or
174 | kittenMock.batteryStatusCall.returns(Result(value: 42))
175 |
176 | // or in case you want this stub to return failure
177 | kittenMock.batteryStatusCall.returns(.failure(ImagineThisIsError))
178 | // or
179 | kittenMock.batteryStatusCall.returns(Result(error: ImagineThisIsError))
180 | ```
181 |
182 | Everything else stays the same :)
183 |
184 | # Matchers
185 | SwiftyMock doesn't have its own matchers, so you can use whatever matchers suits better for you :)
186 |
187 | # Templates
188 | You can generate mocks automatically with [Sourcery](https://github.com/krzysztofzablocki/Sourcery).
189 | First, create sourcery config yml and specify paths to sources, templates, generated output and testable import framework for tests.
190 | You can take a look at how `.sourcery.yml` here in the root looks like.
191 | ```yml
192 | sources:
193 | - ./Example/SwiftyMock/RoboKitten
194 | templates:
195 | - ./SwiftyMock/Templates
196 | output:
197 | path: ./Example/RoboKittenTests/Mocks/Generated
198 | args:
199 | testable: SwiftyMock_Example # here you specify your application module name, that you're importing for testing
200 | ```
201 | Second, annotate protocols that you want to generate mocks for, with `// sourcery: Mock` comment:
202 | ```swift
203 | // sourcery: Mock
204 | protocol RoboKitten {
205 | // ...
206 | }
207 | ```
208 | Third, run sourcery command `sourcery --config .sourcery.yml --watch` if you want to run service that will regenerate mocks every time your source files or templates change.
209 | Or `sourcery --config .sourcery.yml` if you want to generate mocks once.
210 |
--------------------------------------------------------------------------------
/SwiftyMock.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = 'SwiftyMock'
3 | s.version = '0.2.3'
4 | s.summary = 'Some helpers to do Mocking in Swift.'
5 | s.description = <<-DESC
6 | Some helpers to do Mocking in Swift.
7 | Mostly useful for mocking via protocols. Simple solution. Handles most of the cases. Easy setup
8 | DESC
9 |
10 | s.homepage = 'https://github.com/Stanfy/SwiftyMock'
11 | s.license = { :type => 'MIT', :file => 'LICENSE' }
12 | s.author = { 'Stanfy' => 'hello@stanfy.com' }
13 | s.source = { :git => 'https://github.com/Stanfy/SwiftyMock.git', :tag => s.version.to_s }
14 |
15 | s.ios.deployment_target = '8.0'
16 |
17 | s.default_subspec = 'Core'
18 |
19 | s.subspec 'Core' do |cs|
20 | cs.source_files = 'SwiftyMock/Classes/Core/**/*'
21 | end
22 |
23 | s.subspec 'ReactiveCocoa' do |rs|
24 | rs.dependency 'SwiftyMock/Core'
25 | rs.dependency 'ReactiveCocoa', '~> 7.1'
26 | rs.source_files = 'SwiftyMock/Classes/ReactiveCocoa/**/*'
27 | end
28 |
29 | s.subspec 'Templates' do |ts|
30 | ts.dependency 'SwiftyMock/Core'
31 | ts.resources = 'SwiftyMock/Templates/**/*'
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/SwiftyMock/Assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanfy/SwiftyMock/c08979526ad04aa544387646464d58a4c15d7626/SwiftyMock/Assets/.gitkeep
--------------------------------------------------------------------------------
/SwiftyMock/Classes/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanfy/SwiftyMock/c08979526ad04aa544387646464d58a4c15d7626/SwiftyMock/Classes/.gitkeep
--------------------------------------------------------------------------------
/SwiftyMock/Classes/Core/MockUtils.swift:
--------------------------------------------------------------------------------
1 | // A handy Utility for manual function calls testing.
2 | // Since Swift doesn't provide any access to runtime yet, we have to manually mock, stub and spy our calls
3 |
4 | // swiftlint:disable line_length
5 |
6 | // MARK: - Function Call Mock/Stub/Spy
7 |
8 | open class FunctionCall {
9 |
10 | // Spying Call's passed Arguments
11 |
12 | open fileprivate(set) var callsCount: Int = 0
13 | open var called: Bool {
14 | return callsCount > 0
15 | }
16 |
17 | // Stubbing Call with predefined Value
18 | open fileprivate(set) var stubbedValue: Value?
19 | open func returns(_ value: Value) {
20 | stubbedValue = value
21 | }
22 |
23 | // Stubbing Call with prefefined logic
24 | open fileprivate(set) var stubbedBlock: ((Arg) -> Value)?
25 | open func performs(_ block: @escaping (Arg) -> Value) {
26 | stubbedBlock = block
27 | }
28 |
29 | open fileprivate(set) var capturedArguments: [Arg] = []
30 | open var capturedArgument: Arg? {
31 | return capturedArguments.last
32 | }
33 |
34 | fileprivate(set) var stubbedBlocks: [ReturnStub] = []
35 |
36 | open func on(_ filter: @escaping (Arg) -> Bool) -> ReturnContext {
37 | let stub = ReturnStub(filter: filter)
38 | stubbedBlocks += [stub]
39 | return ReturnContext(call: self, stub: stub)
40 | }
41 |
42 | public init() {}
43 |
44 | func capture(_ argument: Arg) {
45 | callsCount += 1
46 | capturedArguments += [argument]
47 | }
48 | }
49 |
50 | public func stubCall(_ call: FunctionCall, argument: Arg, defaultValue: Value? = nil) -> Value {
51 | call.capture(argument)
52 |
53 | for stub in call.stubbedBlocks {
54 | if stub.filter(argument) {
55 | if case let .some(stubbedBlock) = stub.stubbedBlock {
56 | return stubbedBlock(argument)
57 | }
58 |
59 | if case let .some(stubbedValue) = stub.stubbedValue {
60 | return stubbedValue
61 | }
62 | }
63 | }
64 |
65 | if case let .some(stubbedBlock) = call.stubbedBlock {
66 | return stubbedBlock(argument)
67 | }
68 |
69 | if case let .some(stubbedValue) = call.stubbedValue {
70 | return stubbedValue
71 | }
72 |
73 | if case let .some(defaultValue) = defaultValue {
74 | return defaultValue
75 | }
76 |
77 | assertionFailure("stub doesnt' have value to return")
78 |
79 | return call.stubbedValue!
80 | }
81 |
82 | // MARK: - Helpers for stubbing
83 |
84 | open class ReturnContext {
85 | let call: FunctionCall
86 | let stub: ReturnStub
87 | init(call: FunctionCall, stub: ReturnStub) {
88 | self.call = call
89 | self.stub = stub
90 | }
91 |
92 | @discardableResult open func returns(_ value: Value) -> FunctionCall {
93 | stub.stubbedValue = value
94 | return call
95 | }
96 |
97 | @discardableResult open func performs(_ block: @escaping ((Arg) -> Value)) -> FunctionCall {
98 | stub.stubbedBlock = block
99 | return call
100 | }
101 | }
102 |
103 | open class ReturnStub {
104 | let filter: (Arg) -> Bool
105 | fileprivate(set) var stubbedValue: Value?
106 | fileprivate(set) var stubbedBlock: ((Arg) -> Value)?
107 |
108 | init(filter: @escaping (Arg) -> Bool) {
109 | self.filter = filter
110 | }
111 | }
112 |
113 | // MARK: - Function Call Mock/Stub/Spy Without Arguments
114 |
115 | public typealias FunctionVoidCall = FunctionCall
116 |
117 | public func stubCall(_ call: FunctionVoidCall, defaultValue: Value? = nil) -> Value {
118 | return stubCall(call, argument: (), defaultValue: defaultValue)
119 | }
120 |
--------------------------------------------------------------------------------
/SwiftyMock/Classes/ReactiveCocoa/ReactiveExtensions.swift:
--------------------------------------------------------------------------------
1 | // A handy Utility for manual function calls testing.
2 | // Since Swift doesn't provide any access to runtime yet, we have to manually mock, stub and spy our calls
3 |
4 | // swiftlint:disable line_length
5 |
6 | // MARK: Reactive Function Call Mock/Stub/Spy
7 |
8 | import ReactiveSwift
9 | import Result
10 |
11 | // MARK: - Reactive Call Mock/Stub/Spy
12 |
13 | public typealias ReactiveCall = FunctionCall>
14 | public typealias ReactiveVoidCall = FunctionVoidCall>
15 |
16 | // Stub Signal Producer Call
17 |
18 | public func stubCall(_ call: ReactiveCall, argument: Arg, defaultValue: Result? = nil) -> SignalProducer {
19 |
20 | // returning empty signal producer if no default value provide, thus preventing failure assert
21 | if call.stubbedBlocks.isEmpty && call.stubbedBlock == nil && call.stubbedValue == nil && defaultValue == nil {
22 | call.capture(argument)
23 | return .empty
24 | }
25 |
26 | // otherwise - just repeating normal function stubbing flow
27 | let result: Result = stubCall(call, argument: argument, defaultValue: defaultValue)
28 |
29 | // and returning signal producer depending on result value
30 | return SignalProducer(result: result)
31 | }
32 |
33 | // MARK: - Function Call Mock/Stub/Spy Without Arguments
34 |
35 | public func stubCall(_ call: ReactiveVoidCall, defaultValue: Result? = nil) -> SignalProducer {
36 | return stubCall(call, argument: (), defaultValue: defaultValue)
37 | }
38 |
39 | // MARK: - Stub Action Call
40 |
41 | public func stubCall(_ call: ReactiveVoidCall, defaultValue: Result? = nil) -> Action {
42 | return Action {
43 | stubCall(call, defaultValue: defaultValue)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/SwiftyMock/Templates/Mock.stencil:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import SwiftyMock
3 | {% if argument.testable %}@testable import {{ argument.testable }}{% endif %}
4 |
5 | {% macro functionCallType method %}{% if method.parameters.count == 0 %}FunctionVoidCall{% else %}FunctionCall{% endif %}{% endmacro %}
6 |
7 | {% macro functionCallArgumentsType method %}{% if method.parameters.count == 1 %}{{ method.parameters.first.typeName.unwrappedTypeName }}{% else %}({% for param in method.parameters %}{{ param.name }}: {{ param.typeName.unwrappedTypeName }}{% if not forloop.last %}, {% endif %}{% endfor %}){% endif %}{% endmacro %}
8 |
9 | {% macro functionCallReturnType method %}{% if not method.returnTypeName.isVoid %}{{ method.returnTypeName }}{% else %}Void{% endif %}{% endmacro %}
10 |
11 | {% macro stubCallArguments method %}{% if method.parameters.count > 0 %}, argument: {% if method.parameters.count == 1 %}{{ method.parameters.first.name }}{% else %}({% for param in method.parameters %}{{ param.name }}: {{ param.name }}{% if not forloop.last %}, {% endif %}{% endfor %}){% endif %}{% endif %}{% endmacro %}
12 |
13 | {% macro mockVariableGetterCall variable %}let {{ variable.name }}GetCall = FunctionVoidCall<{{ variable.typeName }}>(){% endmacro %}
14 | {% macro mockVariableSetterCall variable %}let {{ variable.name }}SetCall = FunctionCall<{{ variable.typeName }}, Void>(){% endmacro %}
15 |
16 | {% macro mockVariable variable %}
17 | {% call mockVariableGetterCall variable %}
18 | {% if variable.isMutable %}{% call mockVariableSetterCall variable %}{% endif %}
19 | var {{ variable.name }}: {{ variable.typeName }} {
20 | get { return stubCall({{ variable.name }}GetCall) }
21 | {% if variable.isMutable %}set { stubCall({{ variable.name }}SetCall, argument: newValue) }{% endif %}
22 | }
23 | {% endmacro %}
24 |
25 | {% for type in types.protocols where type|annotated:"Mock" %}
26 | class Fake{{ type.name }}: {{ type.name }} {
27 | {% for variable in type.allVariables|!definedInExtension %}
28 | {% call mockVariable variable %}
29 | {% if not forloop.last %}
30 |
31 | {% endif %}
32 | {% endfor %}
33 |
34 | {% for method in type.allMethods|!definedInExtension %}
35 | let {{ method.shortName }}Call = {% call functionCallType method %}<{% if method.parameters.count > 0 %}{% call functionCallArgumentsType method %}, {% endif %}{% call functionCallReturnType method %}>()
36 | func {{ method.name }}{% if method.throws %} throws{% endif %}{% if not method.returnTypeName.isVoid %} -> {{ method.returnTypeName }}{% endif %} {
37 | return stubCall({{ method.shortName }}Call{% call stubCallArguments method %}{% if method.returnTypeName.isVoid %}, defaultValue: ()){% else %}){% endif %}
38 | }
39 | {% if not forloop.last %}
40 |
41 | {% endif %}
42 | {% endfor %}
43 | }
44 | {% if not forloop.last %}
45 |
46 | {% endif %}
47 | {% endfor %}
48 |
--------------------------------------------------------------------------------
/_Pods.xcodeproj:
--------------------------------------------------------------------------------
1 | Example/Pods/Pods.xcodeproj
--------------------------------------------------------------------------------