bruno
bruno

Reputation: 2169

How to access file from bundle in unit tests

I'm doing Unit tests and I'm trying to get a file from bundle, but on line let bundle = Bundle(for: type(of: SecCertificate) I get the error:

Cannot convert value of type 'SecCertificate.Type.Type' to expected argument type 'AnyClass' (aka 'AnyObject.Type')

enum CertificatesMock: CertificatesType {

    case myWebUrl

    var host: [String] {

        switch self {
        case .myWebUrl:
            return ["https://my.web.url/"]
        }
    }

    var certificates: SecCertificate {

        switch self {
        case .myWebUrl:

            let bundle = Bundle(for: type(of: SecCertificate))
            return CertificatesMock.certificate(filename: "myWebUrl", bundle: bundle)
        }
    }

    private static func certificate(filename: String, bundle: Bundle) -> SecCertificate {

        if let filePath = bundle.path(forResource: filename, ofType: "cer") {

            do {

                let data = try Data(contentsOf: URL(fileURLWithPath: filePath))
                let certificate = SecCertificateCreateWithData(nil, data as CFData)!

                return certificate

            } catch {

                fatalError(CertificatesError.noCertificateFound.description + ": " + filename)
            }

        } else {

            fatalError(CertificatesError.noCertificateFound.description + ": " + filename)
        }
    }
}

The problem is that I have that file in my UnitTests target but don't know how to access it.

Upvotes: 2

Views: 1928

Answers (1)

πter
πter

Reputation: 2217

You are trying to access the bundle from an enum, but according to your error it can be only from an AnyClass object.

Cannot convert value of type 'CertificatesMock.Type' to expected argument type 'AnyClass' (aka 'AnyObject.Type')

An enum(In your case CertificatesMock) won't conform to AnyClass, therefore the error. One workaround is to define a class with a property of bundle, and retrieve it from there. It is valid in this case because BundleClass conforms to AnyClass

class BundleClass {
    var bundle: Bundle {
        return Bundle(for: type(of: self))
    }
}

// To use it
let bundle = BundleClass().bundle()

One can wonder if the bundle can be a static member, as it is not really efficient to initialise a new member every time we need the bundle, but it would be invalid too. Again the self would be a BundleClass.Type not AnyClass.

Invalid!

class BundleClass {
    static var bundle: Bundle {
        return Bundle(for: type(of: self))
    }
}

Cannot convert value of type 'BundleClass.Type.Type' to expected argument type 'AnyClass' (aka 'AnyObject.Type')

As a workaround for that you can declare a class inside your enum and using a static member you use your created class to access the bundle:

enum CertificatesMock1 {
    class BundleClass {}
    static var fooBundle: Bundle { return Bundle(for: CertificatesMock1.BundleClass.self) }
}

Upvotes: 5

Related Questions