inline fun <reified TSub : Any> Expect<*>.isA(): Expect<TSub>
Expects that the subject of the assertion is a TSub (the same type or a sub-type) and changes the subject to this type.
Notice, that asserting a function type is flawed.
The actual types are ignored as function types erase to Function0,
Function1 etc. on byte code level, which means the assertion holds as long as the subject is a
function and has the same amount of arguments regardless if the types differ. For instance
assert({x: Int -> "hello"}).isA<String -> Unit>{}
holds, even though (Int) -> String
is clearly not
a (String) -> Unit
.
More generally speaking, the flaw applies to all generic types.
For instance isA<List<String>>
would only check if the subject is a List
without checking if
the element type is actually String
. Or in other words
assert(listOf(1, 2)).isA<List<String>>{}
holds, even though List<Int>
is clearly not a List<String>
.
AssertionError
- Might throw an AssertionError if the assertion made is not correct.
Return
An assertion container with the new type TSub.
inline fun <reified TSub : Any> Expect<*>.isA(noinline assertionCreator: Expect<TSub>.() -> Unit): Expect<TSub>
Expects that the subject of the assertion is a TSub (the same type or a sub-type) and that it holds all assertions the given assertionCreator creates.
Notice, in contrast to other assertion functions which expect an assertionCreator, this function returns not
Expect of the initial type, which was some type T
, but an Expect of the specified type TSub.
This has the side effect that a subsequent call has only assertion functions available which are suited for TSub.
Since Expect is invariant it especially means that an assertion function which was not written in a generic way
will not be available. Fixing such a function is easy (in most cases),
you need to transform it into a generic from. Following an example:
interface Person
class Student: Person
fun Expect<Person>.foo() = "dummy" // limited only to Person, not recommended
fun <T: Person> Expect<T>.bar() = "dummy" // available to Person and all subtypes, the way to go
fun Expect<Student>.baz() = "dummy" // specific only for Student, ok since closed class
val p: Person = Student()
expect(p) // subject of type Person
.isA<Student> { ... } // subject now refined to Student
.baz() // available via Student
.foo() // not available to Student, only to Person, results in compilation error
.bar() // available via T : Person
Notice, that asserting a function type is flawed.
The actual types are ignored as function types erase to Function0,
Function1 etc. on byte code level, which means the assertion holds as long as the subject is a
function and has the same amount of arguments regardless if the types differ. For instance
assert({x: Int -> "hello"}).isA<String -> Unit>{}
holds, even though (Int) -> String
is clearly not
a (String) -> Unit
.
More generally speaking, the flaw applies to all generic types.
For instance isA<List<String>>
would only check if the subject is a List
without checking if
the element type is actually String
. Or in other words
assert(listOf(1, 2)).isA<List<String>>{}
holds, even though List<Int>
is clearly not a List<String>
.
AssertionError
- Might throw an AssertionError if the assertion made is not correct.
Return
An assertion container with the new type TSub.