How do you create an NSError object with underlying errors?

127 Views Asked by At

For unit testing purposes, I need to be able to create an NSError object with the underlyingErrors property set to a certain error.

2

There are 2 best solutions below

1
Leo Dabus On BEST ANSWER

You should always favor using the declared vars like NSPOSIXErrorDomain or NSCocoaErrorDomain instead of string literals. Note that there are already declared CocoaError and POSIXError structs that you can use to generate those errors:

func createFilesystemError() -> NSError {
    NSError(
        domain: CocoaError.errorDomain,
        code: CocoaError.fileNoSuchFile.rawValue,
        userInfo: [
            NSUnderlyingErrorKey: NSError(
                domain: POSIXError.errorDomain,
                code: Int(POSIXError.ENOENT.rawValue)
            )
        ]
    )
}

But the correct way to create these erros is to initialize and cast them to NSError if needed:

extension CocoaError {
    static let fileNotFound: CocoaError = .init(
        .fileNoSuchFile,
        userInfo: [
            NSUnderlyingErrorKey: POSIXError(.ENOENT)
        ]
    )
}

extension NSError {
    static let fileNotFound = CocoaError.fileNotFound as NSError
}

createFilesystemError() == .fileNotFound   // true
0
wristbands On

I figured out how to do it. You have to use the userInfo field when initializing your NSError. Here's an example that creates an error that is usually thrown by FileManager when you try to delete a file that does not exist:

func createFilesystemError() -> NSError {
  let underlyingNSError = NSError(domain: "NSPOSIXErrorDomain", code: 2)
  let userInfo = [NSUnderlyingErrorKey: underlyingNSError]
  return NSError(domain: "NSCocoaErrorDomain", code: 4, userInfo: userInfo)
}