如何在 Swift 中模拟 UIApplication?

How to mock UIApplication in Swift?

我目前在 Swift 中使用 Quick + Nimble 进行单元测试。我正在构建一个 Inviter class,它通过不同的方法发送应用程序邀请。

我需要模拟 UIApplication 以验证我的代码调用了 openURL

到目前为止我的代码:

import Quick
import Nimble
import OCMock

extension Inviter {
    convenience init(usingMockApplication mockApplication: UIApplication) {
        self.init()
        application = mockApplication
    }
}

class MockUIApplication : UIApplication {
    var application = UIApplication.sharedApplication()

    var openedURL: String?

    override func openURL(url: NSURL) -> Bool {
        openedURL = url.absoluteString
        return true
    }
}

class InviterSpec: QuickSpec {
    override func spec() {

        describe("Inviter") {
            var mockApplication = MockUIApplication()
            var inviter = Inviter(usingMockApplication: mockApplication)

            beforeEach() {
                inviter = Inviter(usingMockApplication: mockApplication)
            }

            context("for WhatsApp invites") {
                beforeEach() {
                    inviter.inviteViaWhatsAppWithMessage("Invite Message.")
                }

                it("should tell the application to open WhatsApp") {
                    expect(mockApplication.openedURL).toNot(beNil())
                }

                it("should send WhatsApp the right message") {
                    let message = mockApplication.openedURL?.lastPathComponent
                    expect(message).to(equal("Invite%Message."))
                }
            }
        }
    }
}

在这种方法中,我的应用程序在运行时出错,指出只有一个 UIApplication 是可以理解的。以前,可以使 MockUIApplication 继承自 NSObject,并将其传递进来。不幸的是,Swift 的严格类型检查似乎也阻止了这种情况。

会喜欢任何想法。

你很接近。为您需要的功能使用协议。

protocol UIApplicationProtocol {
    func openURL(url: NSURL) -> Bool
}

extension UIApplication: UIApplicationProtocol {}

那么你只需要使用协议而不是 class

extension Inviter {
    convenience init(usingMockApplication mockApplication: UIApplicationProtocol) {
        self.init()
        application = mockApplication
    }
}

您需要修改 Inviter class 才能同时使用 UIApplicationProtocol