У меня возникла проблема с получением Спока, чтобы высмеять метод, который принимает параметр byte[]
в качестве параметра.Спок: Как издеваться над методом, который принимает один байт []?
Простая игрушка пример того, что не удается идентичным образом к моему производственному коду следующим образом:
import java.util.function.Consumer
import spock.lang.Specification
class ConsumerSpec extends Specification {
// ... elided ...
def '4: parameter is of an array type using single typed argument'() {
given:
def consumer = Mock(Consumer)
when:
consumer.accept([20, 21] as byte[])
then:
consumer.accept(_) >> { byte[] arg ->
assert arg[0] == 20
assert arg[1] == 21
}
}
// ... elided ...
}
Сообщение неудачи
ConsumerSpec > 4: parameter is of an array type using single typed argument FAILED
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '[[[email protected]]' with class 'java.util.Arrays$ArrayList' to class 'java.lang.Byte'
at groovy.lang.Closure.call(Closure.java:423)
at org.spockframework.mock.response.CodeResponseGenerator.invokeClosure(CodeResponseGenerator.java:53)
at org.spockframework.mock.response.CodeResponseGenerator.doRespond(CodeResponseGenerator.java:36)
at org.spockframework.mock.response.SingleResponseGenerator.respond(SingleResponseGenerator.java:31)
at org.spockframework.mock.response.ResponseGeneratorChain.respond(ResponseGeneratorChain.java:45)
at org.spockframework.mock.runtime.MockInteraction.accept(MockInteraction.java:76)
at org.spockframework.mock.runtime.MockInteractionDecorator.accept(MockInteractionDecorator.java:46)
at org.spockframework.mock.runtime.InteractionScope$1.accept(InteractionScope.java:41)
at org.spockframework.mock.runtime.MockController.handle(MockController.java:39)
at org.spockframework.mock.runtime.JavaMockInterceptor.intercept(JavaMockInterceptor.java:72)
at org.spockframework.mock.runtime.DynamicProxyMockInterceptorAdapter.invoke(DynamicProxyMockInterceptorAdapter.java:28)
at ConsumerSpec.4: parameter is of an array type using single typed argument(ConsumerSpec.groovy:52)
я полагаться на поведении, описанном в документации Spock для Computing Return Values в разделе «Тестирование на основе взаимодействия». Я выборочно переписана соответствующие биты ниже:
Если замыкание объявляет один нетипизированное параметр, он получает передается список аргументов метода ... Если замыкание декларирует более чем один параметр или один параметр типизированных, аргументы метода будут отображаться один за другим в параметры закрытия ...
Я добавил еще несколько тестов к вышеуказанной спецификации, чтобы понять, понял ли я эти утверждения. Полная MCVE следующим образом:
$ Gradle --version
------------------------------------------------------------
Gradle 2.13
------------------------------------------------------------
Build time: 2016-04-25 04:10:10 UTC
Build number: none
Revision: 3b427b1481e7303c90be7b05079b05b1c
Groovy: 2.4.4
Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM: 1.8.0_91 (Oracle Corporation 25.91-b14)
OS: Linux 4.4.8-300.fc23.x86_64 amd64
// build.gradle
plugins {
id 'groovy'
}
repositories {
mavenCentral()
}
dependencies {
testCompile(
[group: 'org.spockframework', name: 'spock-core', version: '1.0-groovy-2.4']
)
}
// SRC/тест/заводной/ConsumerSpec.groovy
import java.util.function.Consumer
import spock.lang.Specification
class ConsumerSpec extends Specification {
def '1: parameter is of a non-array type using single untyped argument'() {
given:
def consumer = Mock(Consumer)
when:
consumer.accept('value')
then:
consumer.accept(_) >> { args ->
String arg = args[0]
assert arg == 'value'
}
}
def '2: parameter is of a non-array type using single typed argument'() {
given:
def consumer = Mock(Consumer)
when:
consumer.accept('value')
then:
consumer.accept(_) >> { String arg ->
assert arg == 'value'
}
}
def '3: parameter is of an array type using single untyped argument'() {
given:
def consumer = Mock(Consumer)
when:
consumer.accept([20, 21] as byte[])
then:
consumer.accept(_) >> { args ->
byte[] arg = args[0]
assert arg[0] == 20
assert arg[1] == 21
}
}
def '4: parameter is of an array type using single typed argument'() {
given:
def consumer = Mock(Consumer)
when:
consumer.accept([20, 21] as byte[])
then:
consumer.accept(_) >> { byte[] arg ->
assert arg[0] == 20
assert arg[1] == 21
}
}
def '5: parameter is of an array type without using Mock'() {
given:
def consumer = { byte[] arg ->
assert arg[0] == 20
assert arg[1] == 21
} as Consumer<byte[]>
expect:
consumer.accept([20, 21] as byte[])
}
}
И снова единственное испытание, которое терпит неудачу, - это (4).
Основываясь на сообщении об ошибке, почти так, как будто Spock или Groovy хотят обработать метод издевательства как метод varargs Byte
и распаковать аргумент byte[]
. Единственная зарегистрированная проблема, которую я смог найти, похожа на мою проблему, - это GROOVY-4843, которая была подана против встроенной структуры Groovy и без разрешения.
Есть ли способ получить тест (4), чтобы вести себя так, как ожидалось? То есть, чтобы использовать аргумент типизированного массива при закрытии одного параметра? Или я застрял с использованием формы (3) и должен извлечь аргумент фактического метода из аргумента нетипизированного закрытия?
Спасибо, что нашли время для этого исследования. Казалось бы, это в основном та же проблема, что и GROOVY-4843. Я не знаком с историей Спока, но мне интересно, разве он был раздвоен из первоначальной структуры Groovy/насмешливой структуры и унаследовал эту проблему? Будет хорошим вопросом для @PeterNiederwieser ... –