Ключевое слово object в Kotlin создает синглтон очень удобным способом. Это может использоваться, например, как состояние операции. Spock Framework — одна из наиболее выразительных и удобочитаемых сред тестирования, доступных в экосистеме Java. Давайте посмотрим, как object Kotlin может быть использован в тестах Спока.
Что мы хотим проверить?
У нас есть единственный метод validate в интерфейсе Validator который возвращает статус проверки: Ok или Error .
|
1
2
3
4
5
6
7
|
sealed class ValidationStatusobject 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.classCompiled 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, являются их собственными. |