在Spock中使用GroovyMock或类似方法模拟静态方法

时间:2013-04-05 01:09:30

标签: unit-testing groovy spock powermock powermockito

这里的第一个计时器,如果我错过任何事情,我会道歉。 我希望能够使用Spock来调用静态方法。反馈会很棒

使用groovy模拟器,我以为我能够通过静态调用但没有找到它。 作为背景,我正在改进遗留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返回方法其余部分所需的Thing

如果我直接运用全局模拟,它会返回模拟的实例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
    }
}

但是如果我从ClassUnderTest运行methodUnderTest:

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实例,它在instanceMethod中失败了。

3 个答案:

答案 0 :(得分:19)

Spock只能模拟在Groovy中实现的静态方法。对于使用Java实现的静态方法的模拟,您需要使用GroovyMockPowerMockJMockit等工具。

PS:鉴于这些工具为了实现目标而采取了一些深层技巧,我很想知道它们是否以及如何与Groovy / Spock(而不是Java / JUnit)中实现的测试一起工作。

答案 1 :(得分: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注释是可选的,只有在与现有库存在冲突时才使用它

答案 2 :(得分:0)

我在Groovy / Spock中解决静态方法的方法是通过创建在实际代码中替换掉的代理类。这些代理类仅返回所需的静态方法。您只需将代理类传递给要测试的类的构造函数即可。

因此,在编写测试时,您将接触到代理类(该类将返回静态方法),并且应该能够以这种方式进行测试。