24

I am aware there are a number of questions on how to get the type of an object using Swift.

For example: How do you find out the type of an object (in Swift)?

The reason that I want to find the type is so that I can test that the correct thing is returned within a unit test. The premise being if anyone ever changes it, the test will fail, and we will know to be more careful.

Swift has the is method which returns a boolean as to whether an object is of a certain type. I would like to use is, and then assert that the response is true.

As outlined here (http://www.raywenderlich.com/74138/swift-language-faq) however, and shown in practice.. this throws up an error:

error: 'is' test is always true

The point is that it returns true now.. and i am writing a test so that this is always the case. Stupid swift.

Any ideas how I can test the type of a response using XCTest and swift?

Thanks

Community
  • 1
  • 1
Thomas Clowes
  • 4,529
  • 8
  • 41
  • 73

4 Answers4

33

To get around Swift being too smart, cast the item you are testing to type Any and then test it. For instance, if you want to assert that the function fred() returns an Int

func fred() -> Int {
    return 3
}

assert((fred() as Any) is Int)

Try this in a Playground, and then change the return type to Float and the assert will fire.

vacawama
  • 150,663
  • 30
  • 266
  • 294
10

Just use is operator:

XCTAssertTrue(viewController  is HomeViewController)
0

I think @vacawama 's XCTAssertTrue((value as Any) is Int) notiation is good and @Javier Calatrava Llavería 's notation is also good.

but I decide use just String of type(of:).
It's Simple and Readable.

look following cases.

// Simple And Readable notation
XCTAssertEqual("\(type(of: response))", "DataResponse<Int, Error>")
XCTAssertEqual("\(type(of: transformed))", "DataResponse<Double, Error>")

// @vacawama 's notation
XCTAssertTrue((response.value as Any) is Optional<Int>)
XCTAssertTrue((transformed.value as Any) is Optional<Double>)

And You can make convenience Test AssertType Method like this.

// It's MORE Simple And Readable
KITAssertEqualType(response, "DataResponse<Int, Error>")
KITAssertEqualType(transformed, "DataResponse<Double, Error>")

public func KITAssertEqualType<T>(
    _ expression: @autoclosure () throws -> T,
    _ typeDescription: any StringProtocol,
    _ message: @autoclosure () -> String = "",
    file: StaticString = #filePath, line: UInt = #line
) {
    XCTAssertEqual("\(type(of: try expression()))", String(typeDescription), message(), file: file, line: line)
}
TopChul
  • 419
  • 2
  • 14
-3

If you are explicit about types in your let declarations, maybe you don't need to do anything more complex?

let fred: Int = fred()

Sure, it'll keep your tests from compiling instead of failing when they're run. But it communicates the same "Something in this test is no longer as expected!"

emarley
  • 1
  • 1