XCUITest Stubbing Network Calls

WireMock Implementation

{
"request": {
"method": "GET",
"url": "/people"
},
"response": {
"status": 200,
"headers":
{
"Content-Type" : "application/xml"
},
"bodyFileName": "/people.xml"
}
}
{
"request": {
"method": "GET",
"url": "/list"
},
"response": {
"status": 200,
"headers":
{
"Content-Type" : "application/xml"
},
"jsonBody": []
}
}
{
"request": {
"method": "GET",
"url": "/list",
"bodyPatterns": [
{
"contains": "tom"
}
]
},
"response": {
"status": 200,
"headers":
{
"Content-Type" : "application/xml"
},
"jsonBody": []
}
}

Our Solution

import SBTUITestTunnelServer
import SBTUITestTunnelClient
struct StubHelper {
static func stubFile(fileName: String, url: String) {
let responseFile = SBTStubResponse(fileNamed: fileName)
app.stubRequests(matching: SBTRequestMatch(url: url),
response: responseFile)
}
}
import XCTest
import SBTUITestTunnelServer
import SBTUITestTunnelClient
class MyShoppingListTest: { var app: SBTUITunneledApplication override func setUp() {
app.launchTunnel()
}
override func tearDown() {
app.stubRequestsRemoveAll()
}
func testNoItems() {
StubHelper.stubFile(fileName: "listNone.json", url: ".*/list")
... login and perform any verification ...
}
func testOneItem() {
StubHelper.stubFile(fileName: "listOne.json", url: ".*/list")
... login and perform any verification ...
}
func testTwentyItems() {
StubHelper.stubFile(fileName: "listTwenty.json", url:
".*/list")
... login and perform any verification ...
}
}
import XCTest
import SBTUITestTunnelServer
import SBTUITestTunnelClient
class MyShoppingListTest: { private static var hasRunAtLeastOnce = false
var
app: SBTUITunneledApplication
override func setUp() {
if hasRunAtLeastOnce == false {
hasRunAtLeastOnce = true
app.launchTunnel()
StubHelper.stubFile(fileName: "listNone.json (see note
below)", url: ".*/list")
... login ...
}
}
override func tearDown() {
app.stubRequestsRemoveAll()
}
func testNoItems() {
StubHelper.stubFile(fileName: "listNone.json", url: ".*/list")
... refresh the list (i.e. swipe down to refresh) ...
...verify list...
}
func testOneItem() {
StubHelper.stubFile(fileName: "listOne.json", url: ".*/list")
... refresh the list (i.e. swipe down to refresh) ...
...verify list...
}
func testTwentyItems() {
StubHelper.stubFile(fileName: "listTwenty.json", url:
".*/list")
... refresh the list (i.e. swipe down to refresh) ...
...verify list...
}
}
struct People: Codable {
var name: String
var age: Int?
}
{
"name": "Tom",
"age": 10
}
class PeopleStub: Codable {
var data: People!
init(fileName: String = "OnePerson.json") {
let json = readFile(name: fileName)
self.data = try! JSONDecoder().decode(T.self, from: json)
}
func readFile(name: String) -> Data {
let nameAndExtension = name.components(separatedBy: ".")

guard let path = Bundle(for: type(of:
self)).url(forResource: nameAndExtension.first ?? "",
withExtension: nameAndExtension.last ?? "")
else {
fatalError("File: \(name) doesn't exists")
}
return try! Data(contentsOf: path)
}
func stub() {
let url = ".*/people"
let data = try! JSONEncoder().encode(self.data)

app.stubRequests(matching: SBTRequestMatch(url: requestURL,
query: queryParams), response:
SBTStubResponse(response: strJson))
}
func stubReallyLongName() {
self.data.name = "Thomas John Black Somereallylonglastname"
self.stub()
}
func stubNoAge() {
self.data.age = null
self.stub()
}
}
import XCTest
import SBTUITestTunnelServer
import SBTUITestTunnelClient
class PeopleTest: { var app: SBTUITunneledApplication
let peopleStub = PeopleStub()
override func setUp() {
app.launchTunnel()
}
override func tearDown() {
app.stubRequestsRemoveAll()
}
func testLongName() {
peopleStub.stubReallyLongName()
... perform steps that would trigger the people API call...
}
func testNoAge() {
peopleStub.stubNoAge()
... perform steps that would trigger the people API call...
}
}

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store