MockFive

by DeliciousRaspberryPi

DeliciousRaspberryPi / MockFive

A Mocking Framework for Swift Unit Tests

209 Stars 15 Forks Last release: Not found Apache License 2.0 43 Commits 3 Releases

Available items

No Items, yet!

The developer of this repository has not created any items for sale yet. Need a bug fixed? Help with integration? A different license? Create a request here:

For detailed instructions, see my blog entry!

Installation

Add

pod 'MockFive'
to your Podfile, or include both swift files from the
MockFive
directory to your project.

One Mock, Many Tests

MockFive
allows you to make a single mock for a class or protocol. You can then configure instances of this mock with stubbed implementations. For any commonly used class,
MockFive
can offer a powerful means to satisfy Swift's strict typing system without sacrificing power. Because of Swift's strict typing, you must implement every method you intend to mock with calls to
MockFive
's
stub()
.
// Optional types will return `nil` by default
func myFunc(arg1: Int, arg2: String) -> String? {
    return stub(identifier: "myFunc", arguments: arg1, arg2)
}

// Non-optional types require a default value var customItem = MyCustomClass() // This may be changed later. stub will return new value func myFunc() -> MyCustomClass { return stub(identifier: "myFunc") { customItem } }

In order to work properly, a mocked function must do three things. It must return the result of a call to

stub()
, it must provide a unique string for the
identifier
parameter, and it must pass its arguments through the
arguments
parameter. If the return type of the function is
Void
or is an optional type,
stub()
will return
Void
or
nil
as appropriate by default. In other cases, such as
Int
, a closure must be provided with a default value. In the case of class stubs, it is often useful to call
super
by default. This creates a mock that behaves exactly like a production object, but tracks all method calls and allows stubbing.

Protocol Mocking

import MockFive

//MARK: Production file ------------------------------------------------------------------------------------- struct CustomModel { var id: Int }

protocol MockworthyProtocol { func method() func complexMethod(arg: Int, model: CustomModel, others: Any?...) -> (Int, String) }

//MARK: Testing utilities file ------------------------------------------------------------------------------ struct MockImplementation: MockworthyProtocol, Mock { let mockFiveLock = lock()

func method() { stub(identifier: "method") }
func complexMethod(arg: Int, model: CustomModel, others: Any?...) -> (Int, String) { _ -> (Int, String) in
    return stub(identifier: "complexMethod", arguments: arg, model.id, others) { (37, "stub string") }
}

}

//MARK: Test file -------------------------------------------------------------------------------------------- var mock = MockImplementation()

// Invocation records mock.method() mock.complexMethod(7, model: CustomModel(id: 982), others: 7, nil, 0.23, [0,9]) // (37, "stub string")

mock.invocations[0] // "method()" mock.invocations[1] // "complexMethod(_: 7, model: 982, others: [Optional(7), nil, Optional(0.23), Optional([0, 9])]) -> (Int, String)"

// Function stubbing mock.registerStub("complexMethod") { (90, "Total (42 + 9)") } mock.complexMethod(9, model: CustomModel(id: 7)) // (90, "Total 51")

Class Mocking

import MockFive

//MARK: Production file ------------------------------------------------------------------------------------- struct CustomModel { var id: Int }

class MockworthyClass { func method() {} func complexMethod(arg: Int, model: CustomModel, others: Any?...) -> (Int, String) { return (9, "potatos") } }

//MARK: Testing utilities file ------------------------------------------------------------------------------ class MockwortheClassMock: MockworthyClass, Mock { let mockFiveLock = lock()

override func method() { stub(identifier: "method") { super.method() } }
override func complexMethod(arg: Int, model: CustomModel, others: Any?...) -> (Int, String) { _ -> (Int, String) in
    return stub(identifier: "complexMethod", arguments: arg, model.id, others) { 
        super.complexMethod(arg, model: model, others: others) 
    }
}

}

//MARK: Test file -------------------------------------------------------------------------------------------- var mock = MockwortheClassMock()

// Invocation records mock.method() mock.complexMethod(7, model: CustomModel(id: 982), others: 7, nil, 0.23, [0,9]) // (37, "stub string")

mock.invocations[0] // "method()" mock.invocations[1] // "complexMethod(_: 7, model: 982, others: [Optional(7), nil, Optional(0.23), Optional([0, 9])]) -> (Int, String)"

// Function stubbing mock.registerStub("complexMethod") { (90, "Total (42 + 9)") } mock.complexMethod(9, model: CustomModel(id: 9)) // (90, "Total 51")

See more examples in

TestTrack.playground
in the project!

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.