如何测试Swift枚举与相关值的相等性

 黑暗中的数字 发布于 2023-01-08 11:50

我想测试两个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一样.

7 个回答
  • 我在单元测试代码中使用这个简单的解决方法:

    extension SimpleToken: Equatable {}
    func ==(lhs: SimpleToken, rhs: SimpleToken) -> Bool {
        return String(stringInterpolationSegment: lhs) == String(stringInterpolationSegment: rhs)
    }
    

    它使用字符串插值来执行比较.我不推荐它用于生产代码,但它简洁并且可以完成单元测试.

    2023-01-08 11:51 回答
  • enum MyEnum {
        case None
        case Simple(text: String)
        case Advanced(x: Int, y: Int)
    }
    
    func ==(lhs: MyEnum, rhs: MyEnum) -> Bool {
        switch (lhs, rhs) {
        case (.None, .None):
            return true
        case let (.Simple(v0), .Simple(v1)):
            return v0 == v1
        case let (.Advanced(x0, y0), .Advanced(x1, y1)):
            return x0 == x1 && y0 == y1
        default:
            return false
        }
    }
    

    2023-01-08 11:51 回答
  • 正如其他人所说,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语句进行嵌套开关.

    2023-01-08 11:51 回答
  • 另一种选择是比较案例的字符串表示:

    XCTAssert(String(t1) == String(t2))
    

    例如:

    let t1 = SimpleToken.Number(123) // the string representation is "Number(123)"
    let t2 = SimpleToken.Number(123)
    let t3 = SimpleToken.Name("bob") // the string representation is "Name(\"bob\")"
    
    String(t1) == String(t2) //true
    String(t1) == String(t3) //false
    

    2023-01-08 11:51 回答
  • 实施Equatable是一个矫枉过正的恕我直言.想象一下,你有许多案例和许多不同参数的复杂和大枚举.这些参数也都必须Equatable实现.此外,谁说您在全有或全无的基础上比较枚举案例?如果您正在测试值并且仅存在一个特定的枚举参数,那该怎么办?我强烈建议简单的方法,如:

    if case .NotRecognized = error {
        // Success
    } else {
        XCTFail("wrong error")
    }
    

    ......或在参数评估的情况下:

    if case .Unauthorized401(_, let response, _) = networkError {
        XCTAssertEqual(response.statusCode, 401)
    } else {
        XCTFail("Unauthorized401 was expected")
    }
    

    在此处查找更详细的说明:https://mdcdeveloper.wordpress.com/2016/12/16/unit-testing-swift-enums/

    2023-01-08 11:51 回答
  • 这是另一种选择.除了通过使用if case语法避免嵌套的switch语句之外,它主要与其他语句相同.我认为这使得它更具可读性(/可忍受)并且具有完全避免默认情况的优点.

    enum SimpleToken: Equatable {
        case Name(String)
        case Number(Int)
    }
    extension SimpleToken {
        func isEqual(st: SimpleToken)->Bool {
            switch self {
            case .Name(let v1): 
                if case .Name(let v2) = st where v1 == v2 { return true }
            case .Number(let i1): 
                if case .Number(let i2) = st where i1 == i2 { return true }
            }
            return false
        }
    }
    
    func ==(lhs: SimpleToken, rhs: SimpleToken)->Bool {
        return lhs.isEqual(rhs)
    }
    
    let t1 = SimpleToken.Number(1)
    let t2 = SimpleToken.Number(2)
    let t3 = SimpleToken.Name("a")
    let t4 = SimpleToken.Name("b")
    
    t1 == t1  // true
    t1 == t2  // false
    t3 == t3  // true
    t3 == t4  // false
    t1 == t3  // false
    

    2023-01-08 11:52 回答
  • 对于枚举,结构似乎没有编译器生成的相等运算符.

    "例如,如果您创建自己的类或结构来表示复杂的数据模型,则该类或结构的"等于"的含义不是Swift可以为您猜测的."[1]

    要实现相等比较,可以编写如下内容:

    @infix func ==(a:SimpleToken, b:SimpleToken) -> Bool {
        switch(a) {
    
        case let .Name(sa):
            switch(b) {
            case let .Name(sb): return sa == sb
            default: return false
            }
    
        case let .Number(na):
            switch(b) {
            case let .Number(nb): return na == nb
            default: return false
            }
        }
    }
    

    [1]请参阅https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_43上的 "等效运营商"

    2023-01-08 11:52 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有