1. 简介

在使用 Kotlin 编写测试用例时,常常需要验证一个对象的类型。本文将介绍如何使用 Kotest 测试框架来断言对象是否为特定类型。Kotest 提供了便捷的断言函数,使我们能够轻松完成这类验证。我们一起来看看具体用法!

2. 断言对象是某类型的实例

在 Kotest 中,我们可以通过两个断言函数来验证对象是否为某个类型的实例:shouldBeInstanceOf()shouldBeTypeOf()。我们以一个简单的类继承结构为例:

open class Vehicle(open val speed: Int, open val wheels: Int)

class Car(speed: Int) : Vehicle(speed, 4)
class Motorcycle(speed: Int) : Vehicle(speed, 2)

2.1. 使用 shouldBeInstanceOf()

shouldBeInstanceOf() 用于断言一个对象是某个类或其子类的实例:

test("Car should be instance of Vehicle") {
    val car = Car(10)
    car.shouldBeInstanceOf<Vehicle>()
}

在这个例子中,我们声明了一个 Car 类型的变量 car,并断言它属于 Vehicle 类型(包括其子类)。✅

2.2. 使用 shouldBeTypeOf()

如果我们想严格匹配对象的精确类型(不包括子类),可以使用 shouldBeTypeOf()

test("A Car should be of type Car") {
    val vehicle: Vehicle = Car(10)
    vehicle.shouldBeTypeOf<Car>()
}

这个测试会通过,因为 vehicle 实际上是 Car 类型的实例。但如果我们尝试断言它是 Vehicle 类型:

test("A Car should be of type Car") {
    val car: Vehicle = Car(10)

    car.shouldBeTypeOf<Car>()

    shouldFail {
        car.shouldBeTypeOf<Vehicle>()
    }
}

这段代码中,car.shouldBeTypeOf<Vehicle>() 会失败,因为 car 的实际类型是 Car 而不是 Vehicle。⚠️

shouldBeTypeOf() 更严格,只匹配确切类型;
shouldBeInstanceOf() 更宽松,允许子类匹配。

3. 断言对象不是某类型的实例

除了验证对象是某类型的实例,我们有时也需要验证对象不是某个类型的实例。Kotest 提供了两个对应的断言函数:shouldNotBeInstanceOf()shouldNotBeTypeOf(),它们是前两者的反向版本。

3.1. 使用 shouldNotBeInstanceOf()

shouldNotBeInstanceOf() 用于断言一个对象不是某个类或其子类的实例:

test("Motorcycle should not be instance of Car") {
    val vehicle: Vehicle = Motorcycle(15)
    vehicle.shouldNotBeInstanceOf<Car>()
}

测试通过,因为 Motorcycle 不是 Car 的实例。但如果我们尝试断言它不是 Vehicle 的实例:

test("Motorcycle should not be instance of Vehicle") {
    val motorcycle: Vehicle = Motorcycle(15)

    shouldFail {
        motorcycle.shouldNotBeInstanceOf<Vehicle>()
    }
}

该断言失败,因为 MotorcycleVehicle 的子类。❌

3.2. 使用 shouldNotBeTypeOf()

shouldNotBeTypeOf() 是更严格的断言方式,用于确保对象不是某个确切类型的实例:

test("A Motorcycle should not be of type Car") {
    val vehicle: Vehicle = Motorcycle(15)
    vehicle.shouldNotBeTypeOf<Car>()
}

这个测试通过,因为 vehicle 的类型是 Motorcycle,不是 Car

再来看一个更明显的对比:

test("A Motorcycle should not be of type Vehicle") {
    val motorcycle: Vehicle = Motorcycle(15)
    motorcycle.shouldNotBeTypeOf<Vehicle>()
}

这个测试会通过,因为 motorcycle 的确切类型是 Motorcycle,不是 Vehicle。⚠️

shouldNotBeTypeOf() 只匹配确切类型;
shouldNotBeInstanceOf() 会包含子类。

4. 总结

在本文中,我们学习了如何在 Kotest 中断言对象的类型。总结如下:

  • shouldBeInstanceOf<T>():断言对象是 T 类型或其子类;
  • shouldBeTypeOf<T>():断言对象是确切的 T 类型;
  • shouldNotBeInstanceOf<T>():断言对象不是 T 类型或其子类;
  • shouldNotBeTypeOf<T>():断言对象不是确切的 T 类型。

这些断言函数帮助我们更精确地控制测试逻辑,提升测试的可读性和可靠性。合理使用它们,可以让你的 Kotlin 测试代码更优雅、更健壮。


原始标题:How to Assert the Type of an Object in Kotest