Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking in Swift

How do you mock an object in Swift?

The Mirror protocol sounded promising, but it doesn't do much right now.

So far the only approach I found is to subclass and override all methods of the mocked class. This is of course not a true mock, far from ideal, and a lot of work.

Any other ideas?

Why not OCMock?

From the source:

Can I use OCMock using the language bridge functionality?

Yes, but with limitations. If you are brave. As of now this is highly experimental. There's no guarantee that OCMock will ever fully support Swift.

Known limitations:

  • Tests have to be written in Objective-C
  • Objects that should be mocked must inherit from NSObject
  • No stubbing/expecting/verifying of class methods
like image 886
hpique Avatar asked Jun 11 '14 23:06

hpique


People also ask

What is mocking in Swift?

Mocking in Swift We create a protocol with the function's signature. We then make the real implementation of the function by making URLSession conform to the NetworkClientProtocol . This is easier to understand once we look at how we can invoke it.

What is stubbing and mocking?

Stub: Stub is an object that holds predefined data and uses it to answer calls during tests. Such as: an object that needs to grab some data from the database to respond to a method call. Mocks: Mocks are objects that register calls they receive.

What is meant by mocking data?

What is mocking? Mocking is a process used in unit testing when the unit being tested has external dependencies. The purpose of mocking is to isolate and focus on the code being tested and not on the behavior or state of external dependencies.

What is mock object in IOS?

A mock is slightly more complex than a stub. It returns some fake data and can also verify whether a particular method was called.


Video Answer


2 Answers

NSHipster touches on language features in Swift which make an external mocking library less necessary:

In Swift, classes can be declared within the definition of a function, allowing for mock objects to be extremely self-contained. Just declare a mock inner-class, override and [sic] necessary methods:

func testFetchRequestWithMockedManagedObjectContext() {     class MockNSManagedObjectContext: NSManagedObjectContext {         override func executeFetchRequest(request: NSFetchRequest!, error: AutoreleasingUnsafePointer<NSError?>) -> [AnyObject]! {             return [["name": "Johnny Appleseed", "email": "[email protected]"]]         }     }      ... } 

The ability to create a subclass of your external dependency in the local scope plus the addition of XCTestExpectation solve a lot of the same problems as OCMock.

The one thing that a library such as OCMock provides that is very useful are its "verify" methods to ensure that the mock classes were called. It's possible to manually add this, but the automatic addition is nice.

like image 114
Drew Beaupre Avatar answered Sep 25 '22 22:09

Drew Beaupre


I create my mock classes by wrapping everything in a protocol. I hand roll a mock class to conform to the protocol in question, like so:

protocol Dog: class {     var name: String { get }      func bark() }  class DogImpl: Dog {     var name: String      init(name: String) {         self.name = name     }      func bark() {         print("Bark!")     } }  class DogMock: Dog {     var name = "Mock Dog"     var didBark = false      func bark() {         didBark = true     } } 

I use this in conjunction with dependency injection to achieve full test coverage. It's a lot of boilerplate, but I haven't had any issues with this approach so far.

Regarding subclass mocking, you'll run into trouble with final classes, or if they have non-trivial initializers.

like image 25
Mark Avatar answered Sep 22 '22 22:09

Mark