So let me know if there's a better way to do this that I'm overlooking.
I have a situation in a unit test where I'm giving (Object1) a mock delegate (Mock1). I'm then calling an async function on Object1 that is going to notify Mock1, its delegate of an error (passing an ErrorType). In my test I am trying to confirm that the error that Mock1 received is a specific error.
The problem i'm running into is that ErrorType doesn't conform to Equatable, and I can't extend a protocol to conform to another protocol. Because of this, I can't say in the tests
expect(mockObject.receivedError).to(equal(ThisErrorEnum.SomeError))
I can compare the domains and the codes by hand in each test but that's not very elegant. Temporarily I put this in my test module:
func equal(expectedValue: ErrorType?) -> NonNilMatcherFunc<ErrorType> {
return NonNilMatcherFunc { actualExpression, failureMessage in
failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>"
let actualValue = try actualExpression.evaluate()
if expectedValue == nil || actualValue == nil {
if expectedValue == nil {
failureMessage.postfixActual = " (use beNil() to match nils)"
}
return false
}
return expectedValue! == actualValue!
}
}
func stringify(error: ErrorType?) -> String {
return "Domain: \(error?._domain) | Code: \(error?._code)"
}
func ==(lhs: ErrorType, rhs: ErrorType) -> Bool {
return (lhs._domain == rhs._domain) && (lhs._code == rhs._code)
}
So my question is whether there's an elegant way that already exists to make this comparison, and if not whether adding an equal function to handle ErrorTypes specifically would be useful.
There's no implementation of equality for ErrorType in Nimble. A pull request (with tests) is appreciated though!
—
Sent from my iPhone
On Tue, Sep 29, 2015 at 3:59 PM, Scott Robbins [email protected]
wrote:
So let me know if there's a better way to do this that I'm overlooking.
I have a situation in a unit test where I'm giving (Object1) a mock delegate (Mock1). I'm then calling an async function onObject1that is going to notifyMock1, its delegate of an error (passing an ErrorType). In my test I am trying to confirm that the error thatMock1received is a specific error.
The problem i'm running into is that ErrorType doesn't conform to Equatable, and I can't extend a protocol to conform to another protocol. Because of this, I can't say in the testsexpect(mockObject.receivedError).to(equal(ThisErrorEnum.SomeError))I can compare the domains and the codes by hand in each test but that's not very elegant. Temporarily I put this in my test module:
func equal(expectedValue: ErrorType?) -> NonNilMatcherFunc<ErrorType> { return NonNilMatcherFunc { actualExpression, failureMessage in failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>" let actualValue = try actualExpression.evaluate() if expectedValue == nil || actualValue == nil { if expectedValue == nil { failureMessage.postfixActual = " (use beNil() to match nils)" } return false } return expectedValue! == actualValue! } } func stringify(error: ErrorType?) -> String { return "Domain: \(error?._domain) | Code: \(error?._code)" } func ==(lhs: ErrorType, rhs: ErrorType) -> Bool { return (lhs._domain == rhs._domain) && (lhs._code == rhs._code) }So my question is whether there's an elegant way that already exists to make this comparison, and if not whether adding an
equalfunction to handleErrorTypes specifically would be useful.Reply to this email directly or view it on GitHub:
https://github.com/Quick/Nimble/issues/197
Created a PR with tests
It is quite common to override equality test in an enum if you have associated values
for example:
public enum Error: ErrorType {
case Parsing(reason: String?)
case Response(statusCode: Int)
public var toNSError: NSError {
return NSError(domain: _domain, code: _code, userInfo: userInfo)
}
private var userInfo: [NSObject : AnyObject]? {
var localizedDescription: String?
switch self {
case .Parsing(let reason):
localizedDescription = reason
case .Response(let statusCode):
localizedDescription = NSHTTPURLResponse.localizedStringForStatusCode(statusCode)
}
return localizedDescription.map { [NSLocalizedDescriptionKey: $0] }
}
}
extension Error: Equatable {}
public func == (lhs: Error, rhs: Error) -> Bool {
switch (lhs, rhs) {
case (.Parsing(let lReason), .Parsing(let rReason)):
return lReason == rReason
case (.Response(let lStatusCode), .Response(let rStatusCode)):
return lStatusCode == rStatusCode
default:
return false
}
}
with these changes my equality tests are now failing because an enum is by default an ErrorType
context("when not equal") {
it("should not be equal") {
let error: Error = .Parsing(reason: "test")
let error2: Error = .Response(statusCode: 5)
expect(error) != error2
}
context("with different reason") {
it("should not be equal") {
let error: Error = .Parsing(reason: "test")
let error2: Error = .Parsing(reason: "another test")
expect(error) != error2
}
}
}
Huh, hadn't tried doing that before. I'll have to think about if there's a good way to have the functionality of both. Any suggestions?
Not sure, enums don't inherit an existing type that can be overridden for this behavior. I'll revert this merge commit before release. I didn't consider this case, thanks @sync.
This has been merged into master (#260) using a matchError.
I'll close this issue when a release has been made.
Cut v4.0.0. Closing.
Most helpful comment
This has been merged into master (#260) using a
matchError.I'll close this issue when a release has been made.