SwiftStubKit 0.1.6

SwiftStubKit 0.1.6

Yuta Saito维护。



  • Yuta Saito

StubKit

Build Status codecov

智能占位符系统。

安装

使用 Carthage

github "kateinoigakukun/StubKit"

使用 CocoaPods

pod "StubKit", :git => "https://github.com/kateinoigakukun/StubKit.git"

用法

入门

您可以使用一行代码实例化任何类型的 Decodable

import StubKit

// Codable struct
struct User: Codable {
  let id: Int
  let name: String
  let sex: Sex
}

let stubUser = try Stub.make(User.self)
// User(id: 1234, name: "This is Stub String", sex: .female)

自定义属性

即使属性是被定义为 let,也可以自定义。

let maleUser = try Stub.make(User.self) {
  $0.set(\.sex, value: .male)
}
// User(id: 1234, name: "This is Stub String", sex: .male)

使用 Stubbable

如果您想自定义默认的 stub 值,请遵守 Stubbable

extension String: Stubbable {
  static func stub() -> String {
    return "This is custommized Stub String"
  }
}

let stubUser = try Stub.make(User.self)
// User(id: 1234, name: "This is customized Stub String", sex: .female)

高级用法

struct RandomIntStubProvider: StubProvider {
    func stub<T>(of type: T.Type) -> T? {
        if type is Int.Type {
            return Int.random(in: 0..<100) as? T
        }
        return nil
    }
}

let userStub = Stub(type: User.self, provider: [RandomIntStubProvider()])
try userStub.make() // User(id: 97)
try userStub.make() // User(id: 54)
try userStub.make() // User(id: 12)

需要将非最终类作为 Stubbable 使之遵守?

通过定义 UnsafeStubbable 可以将其设置为 Stubbable

public protocol UnsafeStubbable: Stubbable {
    associatedtype Target = Self
    static func unsafeStub() -> Target
}

extension UnsafeStubbable {
    public static func stub() -> Self {
        return unsafeStub() as! Self
    }
}

extension UIImage: UnsafeStubbable {
    public static func unsafeStub() -> UIImage {
        return #imageLiteral(resourceName: "dummy")
    }
}

它是如何工作的

StubKit 主要使用两种技术。

  • 使用 Decoder 协议进行遍历。
  • 使用不可变的 KeyPath 注入值。
  • 使用 Self 实现存在类型。

使用 Decoder 协议遍历结构体

Swift 有 Decodable 协议,如果一个类型遵循 Decodable,Swift 编译器会生成一些代码来内部解码。因此,我们可以在没有任何配置的情况下将 JSON 解码为 Swift 结构体。StubKit 使用此系统通过 Decoder 构建实例。Decoder 是一个协议,它可以通过键或索引提供值,就像 JSONDecoder。如果我们传递一个递归提供占位符值的 Decoder,我们就可以实例化任何类型的 Decodable 实例。

使用非可变 KeyPath 注入值

我知道这是理所当然的,但 Swift 无法修改用 let 定义的属性。但 Swift 有 MemoryLayout<T>.offset,它提供属性从其地址的偏移量。所以实际上在内存中我们可以修改 let 属性。

使用 Self 的存在类型

具有 associatedtype 或使用 Self 类型的协议不能是存在类型。但将 Self 用于方法的返回类型仅适用于 Swift4.2。(我认为将 Self 用于获取器类型也应该可用。)这项技术使 Stubbable 类型安全。