Моческий статический метод с GroovyMock или аналогичный в Spock
Первый таймер здесь, извинения, если я что-то пропустил.
Я надеюсь получить вызов статического метода, используя Spock. Обратная связь будет отличной
С groovy mocks я думал, что смогу пройти статический звонок, но не нашел его.
Для фона, я в процессе дооснащения тестов в старой Java. Рефакторинг запрещен. Я использую spock-0.7 с groovy -1.8.
Вызов статического метода связан с вызовом экземпляра в этой форме:
public class ClassUnderTest{
public void methodUnderTest(Parameter param){
//everything else commented out
Thing someThing = ClassWithStatic.staticMethodThatReturnsAnInstance().instanceMethod(param);
}
}
staticMethod возвращает экземпляр класса ClassWithStatic
instanceMethod возвращает Вещь, необходимую в остальной части метода
Если я непосредственно выполняю глобальный макет, он возвращает посмеянный экземпляр ok:
def exerciseTheStaticMock(){
given:
def globalMock = GroovyMock(ClassWithStatic,global: true)
def instanceMock = Mock(ClassWithStatic)
when:
println(ClassWithStatic.staticMethodThatReturnsAnInstance().instanceMethod(testParam))
then:
interaction{
1 * ClassWithStatic.staticMethodThatReturnsAnInstance() >> instanceMock
1 * instanceMock.instanceMethod(_) >> returnThing
}
}
Но если я запустил методUnderTest из ClassUnderTest:
def failingAttemptToGetPastStatic(){
given:
def globalMock = GroovyMock(ClassWithStatic,global: true)
def instanceMock = Mock(ClassWithStatic)
ClassUnderTest myClassUnderTest = new ClassUnderTest()
when:
myClassUnderTest.methodUnderTest(testParam)
then:
interaction{
1 * ClassWithStatic.staticMethodThatReturnsAnInstance() >> instanceMock
1 * instanceMock.instanceMethod(_) >> returnThing
}
}
Он выдает реальный экземпляр класса ClassWithStatic, который продолжает терпеть неудачу в своем методе экземпляра.
Ответы
Ответ 1
Спок может только высмеивать статические методы, реализованные в Groovy. Для насмешливых статических методов, реализованных в Java, вам нужно использовать такие инструменты, как GroovyMock, PowerMock или JMockit.
PS: Учитывая, что эти инструменты используют некоторые глубокие уловки для достижения своих целей, мне было бы интересно узнать, насколько хорошо они работают вместе с тестами, реализованными в Groovy/Spock (а не в Java/JUnit).
Ответ 2
Вот как я решил свою аналогичную проблему (издевательский вызов статического метода, который вызывается из другого статического класса) с помощью Spock (v1.0) и PowerMock (v1.6.4)
import org.junit.Rule
import org.powermock.core.classloader.annotations.PowerMockIgnore
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.rule.PowerMockRule
import spock.lang.Specification
import static org.powermock.api.mockito.PowerMockito.mockStatic
import static org.powermock.api.mockito.PowerMockito.when
@PrepareForTest([YourStaticClass.class])
@PowerMockIgnore(["javax.xml.*", "ch.qos.logback.*", "org.slf4j.*"])
class YourSpockSpec extends Specification {
@Rule
Powermocked powermocked = new Powermocked();
def "something something something something"() {
mockStatic(YourStaticClass.class)
when: 'something something'
def mocked = Mock(YourClass)
mocked.someMethod(_) >> "return me"
when(YourStaticClass.someStaticMethod(xyz)).thenReturn(mocked)
then: 'expect something'
YourStaticClass.someStaticMethod(xyz).someMethod(abc) == "return me"
}
}
Аннотация @PowerMockIgnore
не является обязательной, используйте ее только при наличии конфликтов с существующими библиотеками
Ответ 3
Я обошел статические методы в Groovy/Spock, создав прокси-классы, которые подставляются в реальный код. Эти прокси-классы просто возвращают статический метод, который вам нужен. Вы просто передадите прокси-классы в конструктор класса, который вы тестируете.
Таким образом, когда вы пишете свои тесты, вы обращаетесь к прокси-классу (который затем возвращает статический метод), и вы должны иметь возможность проводить тестирование таким образом.