Статьи

Тестирование Котлина со Споком Часть 1 — Объект

Ключевое слово object в Kotlin создает синглтон очень удобным способом. Это может использоваться, например, как состояние операции. Spock Framework — одна из наиболее выразительных и удобочитаемых сред тестирования, доступных в экосистеме Java. Давайте посмотрим, как object Kotlin может быть использован в тестах Спока.

Что мы хотим проверить?

У нас есть единственный метод validate в интерфейсе Validator который возвращает статус проверки: Ok или Error .

1
2
3
4
5
6
7
sealed class ValidationStatus
object Ok : ValidationStatus()
object Error : ValidationStatus()
 
interface Validator<T> {
    fun validate(value: T): ValidationStatus
}

Мы также предоставляем простую реализацию этого интерфейса:

1
2
3
class AdultValidator : Validator<Int> {
    override fun validate(value: Int) = if (value >= 18) Ok else Error
}

Как это проверить со Споком?

Первый — глупый подход

Сначала напишем параметризованный тест для валидатора:

01
02
03
04
05
06
07
08
09
10
11
12
AdultValidator sut = new AdultValidator()
 
def 'should validate age #age'() {
    expect:
        sut.validate(age) == result
    where:
        age | result
        0   | Error
        17  | Error
        18  | Ok
        19  | Ok
}

Мы ожидаем, что это пройдет, но это не удастся … Error и Ok — это классы в коде выше.

Второе — наивный подход

Вместо этого нам нужны экземпляры, поэтому мы немного изменим тест:

01
02
03
04
05
06
07
08
09
10
def 'should validate age #age'() {
    expect:
        sut.validate(age) == result
    where:
        age | result
        0   | new Error()
        17  | new Error()
        18  | new Ok()
        19  | new Ok()
}

И снова, этот тоже не работает. Почему? Это потому, что классы Error и Ok не имеют переопределенного метода equals . Но почему? Мы ожидаем, что объекты Kotlin (созданные с помощью ключевого слова object , а не plain object) будут реализованы правильно. Более того, он правильно работает в Kotlin:

1
fun isOk(status:ValidationStatus) = status == Ok

В-третьих — правильный подход

Давайте посмотрим на файл класса:

1
2
3
4
5
6
$ javap com/github/alien11689/testingkotlinwithspock/Ok.class
Compiled from "Validator.kt"
public final class com.github.alien11689.testingkotlinwithspock.Ok extends com.github.alien11689.testingkotlinwithspock.ValidationStatus {
  public static final com.github.alien11689.testingkotlinwithspock.Ok INSTANCE;
  static {};
}

Если мы хотим получить доступ к реальному объекту, который Kotlin использует в таком сравнении, тогда мы должны получить доступ к статическому свойству класса INSTANCE :

01
02
03
04
05
06
07
08
09
10
def 'should validate age #age'() {
    expect:
        sut.validate(age) == result
    where:
        age | result
        0   | Error.INSTANCE
        17  | Error.INSTANCE
        18  | Ok.INSTANCE
        19  | Ok.INSTANCE
}

Сейчас тест проходит.

Четвертый — альтернативный подход

Мы также можем проверить результат метода без конкретного экземпляра класса объекта и использовать вместо него instanceof или Class#isAssignableFrom .

01
02
03
04
05
06
07
08
09
10
11
12
def 'should validate age #age'() {
    when:
        ValidationStatus result = sut.validate(age)
    then:
        result.class.isAssignableFrom(expected)
    where:
        age | expected
        0   | Error
        17  | Error
        18  | Ok
        19  | Ok
}

Покажи мне код

Код доступен здесь ;

Смотрите оригинальную статью здесь: Тестирование Kotlin с помощью Спока. Часть 1. Объект

Мнения, высказанные участниками Java Code Geeks, являются их собственными.