I have written a test to validate if a function is called :
func test_getTaskLists_doNotCreateOrUpdateTaskListToStorageWhenSynchedLocally() {
...
let (datasource, restAPI, fakeTaskListStorage) = ...
datasource.getTaskLists() { (taskLists, error) -> Void in
...
XCTAssertEqual(1, fakeTaskListStorage.readAllInvocationCount)
...
}
...
}
The function is mocked to bypass super implementation and the issue is that the function returns a Results which I can't figure out to build/mock in order to return a valid object so the compiler stops complaining...I know I could just call super.readAll() but here I actually want to convert my test data (fakeTaskLists) to a fake Result object so everyone is happy...not sure if thats possible
class FakeTaskListsStorageRealm : TaskListStorageRealm {
var fakeTaskLists:[TaskList]?
override func readAll() -> RealmSwift.Results<TaskList> {
readAllInvocationCount += 1
//Here I want to return fakeTaskLists somehow...
}
}
There is no way to instantiate Results directly. Subclassing Results doesn't allow too. I think the best way is hiding Results by protocol like ResultsWrapper rather than using Results directly.
But an easy workaround is using in-memory Realm when testing.
The FakeTaskListsStorageRealm's readAll() can be written using in-memory Realm as follows:
class FakeTaskListsStorageRealm : TaskListStorageRealm {
var fakeTaskLists:[TaskList]?
override func readAll() -> RealmSwift.Results<TaskList> {
readAllInvocationCount += 1
return try! Realm(configuration: Realm.Configuration(inMemoryIdentifier: "test")).objects(TaskList.self)
}
}
Related
I have 3 methods that are related to a specific class which is defined as follows:
class MyClass: NSObject {
func myMethod() {
methodA()
methodB()
methodC()
}
func methodA() {}
func methodB() {}
func methodC() {}
}
I need to test that myMethod has called all 3 methods by the order they are implemented: methodA then methodB then methodC
to be tested with XCode Unit Tests, regardless of the implementation of these methods, I have created a subclass in the test case that looks like the following:
class ChildClass: MyClass {
var method1CallingDate: Date?
var method2CallingDate: Date?
var method3CallingDate: Date?
override func methodA() {
super.methodA()
method1CallingDate = Date()
}
override func methodB() {
super.methodB()
method2CallingDate = Date()
}
override func methodC() {
super.methodC()
method3CallingDate = Date()
}
}
Now in the test method, I start by calling those 3 methods, then I assert that all three dates are not nil first, then compare them like this:
XCTAssertLessThan(method1CallingDate, method2CallingDate)
XCTAssertLessThan(method2CallingDate, method3CallingDate)
The problem I ran into was that the test sometimes succeeds and sometimes fails, i guess due to Date object is (randomly) the same between 2 of the method calls.
Is there a better way to test the order of calling multiple methods ?
p.s. this is easily done in the Android SDK org.mockito.Mockito.inOrder
First, make a mock object that records the order. No dates, no strings. Just an enumeration.
class MockMyClass: MyClass {
enum invocation {
case methodA
case methodB
case methodC
}
private var invocations: [invocation] = []
override func methodA() {
invocations.append(.methodA)
}
override func methodB() {
invocations.append(.methodB)
}
override func methodC() {
invocations.append(.methodC)
}
func verify(expectedInvocations: [invocation], file: StaticString = #file, line: UInt = #line) {
if invocations != expectedInvocations {
XCTFail("Expected \(expectedInvocations), but got \(invocations)", file: file, line: line)
}
}
}
Then in the test:
mock.verify(expectedInvocations: [.methodA, .methodB, .methodC])
No async waiting. Simple to call. Clear failure messages.
You could do something like this using a String to keep track of the order:
class ChildClass: MyClass {
var order = ""
override func methodA() {
super.methodA()
order = String((order + "A").suffix(3))
}
override func methodB() {
super.methodB()
order = String((order + "B").suffix(3))
}
override func methodC() {
super.methodC()
order = String((order + "C").suffix(3))
}
}
Then, just check that order is "ABC".
Or, if it is valid to call B multiple times between A and C:
class ChildClass: MyClass {
var order = ""
override func methodA() {
super.methodA()
order = order.replacingOccurrences(of: "A", with: "") + "A"
}
override func methodB() {
super.methodB()
order = order.replacingOccurrences(of: "B", with: "") + "B"
}
override func methodC() {
super.methodC()
order = order.replacingOccurrences(of: "C", with: "") + "C"
}
}
Example:
let c = ChildClass()
c.methodA()
c.methodB()
c.methodB()
c.methodC()
print(c.order)
ABC
I've become a fan of using XCTestExpectation for this kind of thing. Here's an option.
class MyTestableClass: MyClass {
var methodAHandler: (() -> Void)?
// ...
override func methodA() {
methodAHandler?()
super.methodA()
}
And then in your test case
let expA = XCTestExpectation(description: "Method A Called")
let expB = ...
let expo = ...
objectUnderTest.methodAHandler = { expA.fulfill() }
/// ...
objectUnderTest.myMethod()
// ensure you use the enforceOrder param, which is optional
wait(for: [expA, expB, expC], timeout: 1.0, enforceOrder: true)
XCTestExpectation is made more for async testing, so the wait is slightly funny. But, it does do what you need, and would keep working even if eventually the internals of myMethod become asynchronous for some reason.
While I haven't used it myself, you also might want to check out Cuckoo. It's a mocking framework for Swift.
You're not asking the right question here. From a unit testing point of view you should not know/care that the tested method calls other methods, or even if other methods exist.
Unit tests should validate some observable result of the tested method. Anything that happens inside the tested method is irrelevant in the context of a unit test.
That's because unit tests should validate that the unit behaves as expected, i.e. they should validate against the specifications, not against the implementation.
Let's consider a simple example, unit testing a isPrime(n) function. Unless you're doing performance testing, you only care if the function returns the appropriate result for a couple of numbers. You don't care if the function checks all possible divisors, or if it uses a database of all known prime numbers, or if delegates the prime check to some 3rd party library/service.
The situation is not much different from yours. The fact that the three methods are called in a certain order needs to be validate via the external interface of the tested unit. For example if the three methods make API calls, then mock the API client and expect it to be requested three times, and with the expected URL/payload. If calling the three methods don't result in any noticeable changes, then there's not much you can test from the start, so again the fact that three methods are called in a certain order become irrelevant.
Unit testing is about validating the result of the execution of that unit, not anything more. Now, in an imperative programming language, the input->output functions are a minority, however this doesn't mean that we can't indirectly test if the function behaves as expected. You can use mocks, or validate some properties of the object after the function executes. Again, if there are no ways of externally checking the order of methods, then you have no specs to validate against.
I have defined my own class with methods that fits signature of URLSession complete callback, e. g. (Data?, Response?, Error?) -> Void.
The method contains common logic for handling response, e. g. checking data, parsing it etc.
Now I would like to unit test this method. The methods contains some verification, for instance,
guard let data = data else {
//some logic
return
}
Here I would like to test that function will really be terminated. Of course it is not possible to achieve it against void return (I think so, maybe I missed something).
Another option - mark the method as throws, and then test for a specific errors. But then this method will not fit into URLSession.shared.dataTask method.
Am I paranoid about these things? Is there any possibility to achieve it?
Thanks in advance.
Usually I try to separate the query logic into several parts:
1) Router 2) API client which uses a router 3) mapping model
And all this parts you can test.
How you can test API client:
fileprivate func testPerformanceOfGetNewsFromAPI() {
let expectationTimeout: Double = 30.0
self.measure {
let expectation = self.expectation(description: "Get gifters")
NewsAPIClient.getNews(closure: { response in
expectation.fulfill()
})
self.waitForExpectations(timeout: expectationTimeout) { error in
XCTAssertNil(error)
}
}
}
This test will check. Could APIClient receive an response within 30 seconds.
How you can test mapping:
For mapping, I use JASON: https://github.com/delba/JASON
Setup your swift file:
import XCTest
import JASON
#testable import ProjectName
final class NewsTests: XCTestCase {
// MARK: - Properties
fileprivate var news: News!
// MARK: - Lyfecycles
override func setUp() {
super.setUp()
news = mockExample()
}
override func tearDown() {
news = nil
super.tearDown()
}
}
Then, create in this class your mock:
fileprivate func mockExample() -> ExampleModel? {
let data: Data
let json: JSON
do {
try data = Data(resource: "MyExampleFile.json") // Here enter your JSON example file. Target member ship for this file should be your test target
try json = JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions()) as! JSON
} catch let error {
XCTFail(error.localizedDescription)
return nil
}
let model = ExampleModel(json: json)
return model
}
Then, you can write test in this class:
fileprivate func testMapping() {
XCTAssertNotNil(news)
XCTAssertEqual(news.title, mockExample()?.title)
XCTAssertEqual(news.text, mockExample()?.text)
XCTAssertEqual(news.timeStamp, mockExample()?.timeStamp)
}
In the testing logic, you can also add image uploads (if they are present in JSON). Thus, you can check if the current model is correct for you, can process the JSON response.
I am programming an app which utilizes a parse-server (hosted by heroku) database. I have several functions which pull information from the DB, but they are all inherently asynchronous (because of the way parse's .findObjectinBackground works.) The issue with this as that the later DB queries require information from previous queries. Since the information being pulled is asynchronous, I decided to implement PromiseKit to ensure that the object has been found from findObjectinBackground from the first query, before running the second query.
The general form of the queries is as follows:
let query = PFQuery(classname: "Hello")
query?.findObjectsInBackground(block: { (objects, error) in
if let objectss = objects{
for object in objectss{ //object needs to be pulled
arrayOfInterest.append(object)
//array must be appended before moving on to next query
}
}
})
I just do not know how exactly to do this. This is the way I would like to implement it:
import PromiseKit
override func viewDidLoad(){
when(/*query object is retrieved/array is appended*/).then{
//perform the next query
}
}
I simply don't know exactly what to put in the when() and the .then{}. I tried making the queries into their own individual functions and calling them inside those two (when and then) functions, but I basically get told that I cannot because they return void. Also, I cannot simply ensure the first query is run in the when() as the query.findObjectinBackground(in the query) being asynchronous is the issue. The object specifically needs to be pulled, not just the query run, before the next one can fire.
Do you want create your promise?
You need write a function that return a Promise<Any>. In your case, need to encapsulate the entire code inside of Promise { fulfill, reject in HERE}. For example:
func foo(className: String) -> Promise<[TypeOfArrayOfInterest]> {
return Promise { fulfill, reject in
let query = PFQuery(classname: className)
query?.findObjectsInBackground(block: { (objects, error) in
if let error = error {
reject(error) // call reject when some error happened
return
}
if let objectss = objects {
for object in objectss{
arrayOfInterest.append(object)
}
fulfill(arrayOfInterest) // call fulfill with some value
}
})
}
}
Then, you call this function in firstly:
firstly {
foo(className: "Hello")
}.then { myArrayOfInterest -> Void in
// do thing with myArrayOfInterest
}.catch { error in
// some error happened, and the reject was called!
}
Also, I wrote a post in my blog about, among other things, PromiseKit and architecture. It may be helpful: http://macalogs.com.br/ios/rails/ifce/2017/01/01/experiencias-eventbee.html
Edit
More complete example:
func foo() -> Promise<Int> {
...
}
func bar(someText: String) -> Promise<String> {
...
}
func baz() -> Promise<Void> {
...
}
func runPromises() {
firstly {
foo()
}.then { value -> Promise<Any> in
if value == 0 {
return bar(someText: "no")
} else {
return bar(someText: "yes")
}
}.then { _ /* I don't want a String! */ -> Promise<Void> in
baz()
}.catch { error in
// some error happened, and the reject was called!
}
}
Or if you don't want a catch:
_ = firstly {
foo()
}.then { _ in
// do some thing
}
Swift have a greate type inference, but, when use PromiseKit, I recommend always write a type in then closure, to avoid erros.
I have some expensive promises that get called in different spots. Ideally, I'd like to just chain off an existing in-flight promise (with an optional force), so I find myself doing something like this:
class Expensive {
var fooPromise : Promise<Foo>?
var barPromise : Promise<Bar>?
func doExpensiveFoo(force: bool = false) -> Promise<Foo> {
if let existing = fooPromise where existing.pending || (existing.fufilled && !force) {
// Return the existing promise
return existing
}
// Start a new Foo
return firstly {
// ...
}
}
func doExpensiveBar(force: bool = false) -> Promise<Bar> {
if let existing = barPromise where existing.pending || (existing.fufilled && !force) {
// Return the existing promise
return existing
}
// Start a new Bar
return firstly {
// ...
}
}
}
But that feels like a fair amount of boiler-plate (a local variable for each promise, and the existing chunk at the start of each function), so I'm wondering if anyone has seen a good pattern for abstracting away the variables and wrapper?
To borrow a term from Python, I'm looking for a decorator that would hide all that. Something like:
class Expensive {
private func startFoo() -> Promise<Foo> {
return firstly {
//..
}
}
public doExpensiveFoo = wrapExpensive(startFoo)
}
Any suggestions, or should I look at rolling my own?
I'm no expert, but this pattern worked for me:
private var fooPromise : Promise<Foo>?
func doExpensiveFoo() -> Promise<Foo> {
if let fooPromise = self.fooPromise, fooPromise.isPending {
// return the pending promise
return fooPromise
}
// reassign a newly created promise
fooPromise = firstly {
// do your thing
...
}
return fooPromise!
}
What I like about this pattern is that the method handles pending state internally, and that the promise automatically re-executes if called after it is finished. This allows callers to be ignorant of the internal mechanism or the state of the promise. Obviously, if you need to caller to be part of the decision, then keep the "force" flag approach.
I do not see any common base of Foo and Bar in your example. But even if they would have one Swift still does not support covariance on generic type parameters. At first you would need to create a common protocol for both types. Maybe this helps you to get on track:
Storing generic objects in Swift Array
I'm trying to create a protocol in Swift I can use for object construction. The problem I'm running into is that I need to store the type information so the type can be constructed later and returned in a callback. I can't seem to find a way to store it without either crashing the compiler or creating build errors. Here's the basics (a contrived, but working example):
protocol Model {
init(values: [String])
func printValues()
}
struct Request<T:Model> {
let returnType:T.Type
let callback:T -> ()
}
We have a simple protocol that declares a init (for construction) and another func printValues() (for testing). We also define a struct we can use to store the type information and a callback to return the new type when its constructed.
Next we create a constructor:
class Constructor {
var callbacks: [Request<Model>] = []
func construct<T:Model>(type:T.Type, callback: T -> ()) {
callback(type(values: ["value1", "value2"]))
}
func queueRequest<T:Model>(request: Request<T>) {
callbacks.append(request)
}
func next() {
if let request = callbacks.first {
let model = request.returnType(values: ["value1", "value2"])
request.callback(model)
}
}
}
A couple things to note: This causes a compiler crash. It can't figure this out for some reason. The problem appears to be var callbacks: [Request<Model>] = []. If I comment out everything else, the compiler still crashes. Commenting out the var callbacks and the compiler stops crashing.
Also, the func construct works fine. But it doesn't store the type information so it's not so useful to me. I put in there for demonstration.
I found I could prevent the compiler from crashing if I remove the protocol requirement from the Request struct: struct Request<T>. In this case everything works and compiles but I still need to comment out let model = request.returnType(values: ["value1", "value2"]) in func next(). That is also causing a compiler crash.
Here's a usage example:
func construct() {
let constructor = Constructor()
let request = Request(returnType: TypeA.self) { req in req.printValues() }
//This works fine
constructor.construct(TypeA.self) { a in
a.printValues()
}
//This is what I want
constructor.queueRequest(request)
constructor.next() //The callback in the request object should be called and the values should print
}
Does anyone know how I can store type information restricted to a specific protocol to the type can later be constructed dynamically and returned in a callback?
If you want the exact same behavior of next I would suggest to do this:
class Constructor {
// store closures
var callbacks: [[String] -> ()] = []
func construct<T:Model>(type:T.Type, callback: T -> ()) {
callback(type(values: ["value1", "value2"]))
}
func queueRequest<T:Model>(request: Request<T>) {
// some code from the next function so you don't need to store the generic type itself
// **EDIT** changed closure to type [String] -> () in order to call it with different values
callbacks.append({ values in
let model = request.returnType(values: values)
request.callback(model)
})
}
func next(values: [String]) {
callbacks.first?(values)
}
}
Now you can call next with your values. Hopefully this works for you.
EDIT: Made some changes to the closure type and the next function
Unfortunately there is no way to save specific generic types in an array and dynamically call their methods because Swift is a static typed language (and Array has to have unambiguous types).
But hopefully we can express something like this in the future like so:
var callbacks: [Request<T: Model>] = []
Where T could be anything but has to conform to Model for example.
Your queueRequest method shouldn't have to know the generic type the Request it's being passed. Since callbacks is an array of Request<Model> types, the method just needs to know that the request being queued is of the type Request<Model>. It doesn't matter what the generic type is.
This code builds for me in a Playground:
class Constructor {
var callbacks: [Request<Model>] = []
func construct<T:Model>(type:T.Type, callback: T -> ()) {
callback(type(values: ["value1", "value2"]))
}
func queueRequest(request: Request<Model>) {
callbacks.append(request)
}
func next() {
if let request = callbacks.first {
let model = request.returnType(values: ["value1", "value2"])
request.callback(model)
}
}
}
So I found an answer that seems to do exactly what I want. I haven't confirmed this works yet in live code, but it does compile without any errors. Turns out, I needed to add one more level of redirection:
I create another protocol explicitly for object construction:
protocol ModelConstructor {
func constructWith(values:[String])
}
In my Request struct, I conform to this protocol:
struct Request<T:Model> : ModelConstructor {
let returnType:T.Type
let callback:T -> ()
func constructWith(values:[String]) {
let model = returnType(values: values)
callback(model)
}
}
Notice the actual construction is moved into the Request struct. Technically, the Constructor is no longer constructing, but for now I leave its name alone. I can now store the Request struct as ModelConstructor and correctly queue Requests:
class Constructor {
var callbacks: [ModelConstructor] = []
func queueRequest(request: Request<Model>) {
queueRequest(request)
}
func queueRequest(request: ModelConstructor) {
callbacks.append(request)
}
func next() {
if let request = callbacks.first {
request.constructWith(["value1", "value2"])
callbacks.removeAtIndex(0)
}
}
}
Note something special here: I can now successfully "queue" (or store in an array) Request<Model>, but I must do so indirectly by calling queueRequest(request: ModelConstructor). In this case, I'm overloading but that's not necessary. What matters here is that if I try to call callbacks.append(request) in the queueRequest(request: Request<Model>) function, the Swift compiler crashes. Apparently we need to hold the compiler's hand here a little so it can understand what exactly we want.
What I've found is that you cannot separate Type information from Type Construction. It needs to be all in the same place (in this case it's the Request struct). But so long as you keep construction coupled with the Type information, you're free to delay/store the construction until you have the information you need to actually construct the object.