这篇文章主要围绕如何测试Swift枚举与关联值的相等性和swift枚举类型展开,旨在为您提供一份详细的参考资料。我们将全面介绍如何测试Swift枚举与关联值的相等性的优缺点,解答swift枚举类型的相
这篇文章主要围绕如何测试 Swift 枚举与关联值的相等性和swift枚举类型展开,旨在为您提供一份详细的参考资料。我们将全面介绍如何测试 Swift 枚举与关联值的相等性的优缺点,解答swift枚举类型的相关问题,同时也会为您带来7.5 Swift枚举关联值、7.6 Swift中switch提取枚举关联值、arrays – 使用关联值映射swift枚举、iOS swift 单元测试 - 如何测试进行 api 调用的函数?的实用方法。
本文目录一览:- 如何测试 Swift 枚举与关联值的相等性(swift枚举类型)
- 7.5 Swift枚举关联值
- 7.6 Swift中switch提取枚举关联值
- arrays – 使用关联值映射swift枚举
- iOS swift 单元测试 - 如何测试进行 api 调用的函数?
如何测试 Swift 枚举与关联值的相等性(swift枚举类型)
我想测试两个 Swift 枚举值的相等性。例如:
enum SimpleToken { case Name(String) case Number(Int)}let t1 = SimpleToken.Number(123)let t2 = SimpleToken.Number(123)XCTAssert(t1 == t2)
但是,编译器不会编译相等表达式:
error: could not find an overload for ''=='' that accepts the supplied arguments XCTAssert(t1 == t2) ^~~~~~~~~~~~~~~~~~~
我是否确实定义了自己的等式运算符重载?我希望 Swift 编译器能够自动处理它,就像 Scala 和 Ocaml 一样。
答案1
小编典典斯威夫特 4.1+
正如有帮助地指出的那样,从 Swift4.1 开始(由于SE-0185,Swift
还支持综合Equatable
和Hashable
具有关联值的枚举。
因此,如果您使用的是 Swift 4.1 或更高版本,以下内容将自动合成必要的方法,以便XCTAssert(t1 ==t2)
有效。关键是将Equatable
协议添加到您的枚举中。
enum SimpleToken: Equatable { case Name(String) case Number(Int)}let t1 = SimpleToken.Number(123)let t2 = SimpleToken.Number(123)
在 Swift 4.1 之前
正如其他人所指出的,Swift 不会自动合成必要的相等运算符。不过,让我提出一个更清洁(恕我直言)的实现:
enum SimpleToken: Equatable { case Name(String) case Number(Int)}public func ==(lhs: SimpleToken, rhs: SimpleToken) -> Bool { switch (lhs, rhs) { case let (.Name(a), .Name(b)), let (.Number(a), .Number(b)): return a == b default: return false }}
这远非理想——有很多重复——但至少你不需要在内部使用 if 语句进行嵌套切换。
7.5 Swift枚举关联值
/**
枚举相关值
可以让枚举值对应的原始值不是唯一的,而是一个变量.
每一个枚举可以是在某种模式下的一些特定值
后面加一个 元组
*/
enum LinesegmentDescriptor {
case StartAndEndPattern(start:Double,end:Double)
case StartAndLengthPattern(start:Double,length:Double)
}
var lsd = LinesegmentDescriptor.StartAndLengthPattern(start: 0.0,length: 100.0)
lsd = LinesegmentDescriptor.StartAndEndPattern(start: 0.0,end: 50.0)
print("--------->")
print(lsd)
// 利用switch提取枚举关联值
switch lsd {
case let .StartAndEndPattern(s,e):
print("start = \(s) end = \(e)")
case .StartAndLengthPattern(let s,let l):
print("start = \(s) lenght = \(l)")
}
// 输出结果: start = 0.0 end = 50.0
7.6 Swift中switch提取枚举关联值
/**
枚举相关值
可以让枚举值对应的原始值不是唯一的,而是一个变量.
每一个枚举可以是在某种模式下的一些特定值
后面加一个 元组
*/
enum LinesegmentDescriptor {
case StartAndEndPattern(start:Double,end:Double)
case StartAndLengthPattern(start:Double,length:Double)
}
var lsd = LinesegmentDescriptor.StartAndLengthPattern(start: 0.0,length: 100.0)
lsd = LinesegmentDescriptor.StartAndEndPattern(start: 0.0,end: 50.0)
print("--------->")
print(lsd)
// 利用switch提取枚举关联值
switch lsd {
case let .StartAndEndPattern(s,e):
print("start = \(s) end = \(e)")
case .StartAndLengthPattern(let s,let l):
print("start = \(s) lenght = \(l)")
}
// 输出结果: start = 0.0 end = 50.0
arrays – 使用关联值映射swift枚举
enum Content { case Image(ShareableImage) case Video(ShareableVideo) }
现在让我们来看一系列视频和图像案例.
let media: [Content] = [*a lot of enum cases inside here*]
到目前为止,上面的所有代码都无法在代码库中以任何方式进行更改,我需要使用它.
这开始我的问题:
让我们用媒体过滤数组,只对图像情况进行过滤
let imageOnlyCases: [Content] = media.filter { item -> Bool in switch item { case .Image: return true default: return false } }
下一步,我想从枚举数组获取其关联值的数组
[Content] -> [ShareableImage] by using map.
所以我这样做
let shareablemages = imageOnlyCases.map { imageCase -> ShareableImage in switch imageCase { case .Image(let image): return image default: return WHAT TO DO HERE? } }
你看,我有一个返回类型的问题..我知道枚举案例都是.Image ..我想要一个简单的地图.但快速的语法并没有帮助我.
有任何想法吗?
解决方法
/* Example */ enum Foo { case Bar(Int) case Baz(Int) } let foo: [Foo] = [.Bar(1),.Bar(9),. Baz(3),.Bar(39),.Baz(5)] /* 1. using ''switch'' */ let barOnlyValues: [Int] = foo.flatMap { switch $0 { case .Bar(let val): return val case _: return nil }} /* 2. alternatively,as pointed out in MartinR:s answer; as you''re only looking for a single case,the alternative ''if case let'' clause Could be preferred over ''switch'': */ let barOnlyValuesAlt: [Int] = foo.flatMap { if case let .Bar(val) = $0 { return val } else { return nil }} print(barOnlyValues) // [1,9,39]
应用于您的用例:请注意,您无需执行过滤来创建imageOnlyCases数组,因为您可以直接在媒体数组上应用上述内容:
/* 1. using switch */ let shareableImages : [ShareableImage] = media.flatMap { switch $0 { case .Image(let image): return image case _: return nil }} /* 2. ''if case let'' alternative,as per MartinR:s suggestion */ let shareableImagesAlt : [ShareableImage] = media.flatMap { if case let .Image(image) = $0 { return image } else { return nil }}
免责声明:我无法在实践中验证您的具体用例,因为我无权访问ShareableImage类/结构.
(感谢@MartinR的建议,即.map {…} .flatMap {…}可以简化为.flatMap {…}).
iOS swift 单元测试 - 如何测试进行 api 调用的函数?
这取决于您想要测试的 login use case
的哪个“部分”,您项目的具体 HTTPClient? (URLSession、Alamofire 等...),或此服务的实现,但我会给您一些建议。
尝试使用 DI(依赖注入)来准备声明(类、结构、函数...)以使用协议或继承进行测试(协议是大多数情况下的最佳选择)。然后,评估所有可能的响应情况。我为登录服务用例演示做了一个简单的实现。
//
// Created by Wilmer Barrios.
//
import XCTest
// Business Logic
struct LoginResponse {
let succeed: Bool
}
protocol LoginService {
func login(username: String,password: String,completion: @escaping (Result<LoginResponse,Error>) -> Void)
}
// Implementation
class LoginController {
// Presented values
var presentedSucceedMessage: String?
var presentedErrorMessage: String?
// Elements (Could be textfields)
var username: String = ""
var password: String = ""
private let service: LoginService
init(service: LoginService) {
self.service = service
}
func login() {
service.login(username: username,password: password,completion: { [weak self] result in
if let response = try? result.get(),response.succeed {
self?.presentedSucceedMessage = "Login succeed!"
} else {
self?.presentedErrorMessage = "Login error!"
}
})
}
}
class LoginControllerTests: XCTestCase {
func test_init_doesNotLogin() {
let (_,service) = makeSUT()
XCTAssertEqual(service.callCount,0)
}
func test_login_doesLoadService() {
let (sut,service) = makeSUT()
sut.login()
XCTAssertEqual(service.callCount,1)
}
func test_loginSucceed_presentsSucceedMessage() {
let (sut,service) = makeSUT()
sut.login()
service.complete(result: .success(makeLoginResponse()))
XCTAssertEqual(sut.presentedSucceedMessage,"Login succeed!")
XCTAssertNil(sut.presentedErrorMessage)
}
func test_loginError_presentsErrorMessage() {
let (sut,service) = makeSUT()
sut.login()
service.complete(result: .success(makeLoginResponse(succeed: false)))
XCTAssertEqual(sut.presentedErrorMessage,"Login error!")
XCTAssertNil(sut.presentedSucceedMessage)
}
func test_loginFailed_presentsErrorMessage() {
let (sut,service) = makeSUT()
sut.login()
service.complete(result: .failure(makeError()))
XCTAssertEqual(sut.presentedErrorMessage,"Login error!")
XCTAssertNil(sut.presentedSucceedMessage)
}
// MARK: Helpers
private func makeError() -> Error {
return NSError(domain: "anyError",code: 1)
}
private func makeLoginResponse(succeed: Bool = true) -> LoginResponse {
return LoginResponse(succeed: succeed)
}
private func makeSUT() -> (sut: LoginController,service: LoginServiceMock) {
let service = LoginServiceMock()
let sut = LoginController(service: service)
return (sut,service)
}
private class LoginServiceMock: LoginService {
var callCount: Int = 0
private var completion: ((Result<LoginResponse,Error>) -> Void)?
func login(username: String,Error>) -> Void) {
callCount += 1
self.completion = completion
}
// Helpers
func complete(result: Result<LoginResponse,Error>) {
completion?(result)
}
}
}
在这个例子中,您可以请求任何登录服务,可以是您自己的 API、Firebase、任何 SDK,甚至是本地的!,您只需要让服务客户端符合 LoginService
协议。即 AlamoFireLoginClient
、URLSessionLoginClient
、FirebaseLoginClient
等
希望能帮到你!
今天关于如何测试 Swift 枚举与关联值的相等性和swift枚举类型的讲解已经结束,谢谢您的阅读,如果想了解更多关于7.5 Swift枚举关联值、7.6 Swift中switch提取枚举关联值、arrays – 使用关联值映射swift枚举、iOS swift 单元测试 - 如何测试进行 api 调用的函数?的相关知识,请在本站搜索。
本文标签: