Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 在Spock中使用GroovyMock或类似工具模拟静态方法_Unit Testing_Groovy_Spock_Powermock_Powermockito - Fatal编程技术网

Unit testing 在Spock中使用GroovyMock或类似工具模拟静态方法

Unit testing 在Spock中使用GroovyMock或类似工具模拟静态方法,unit-testing,groovy,spock,powermock,powermockito,Unit Testing,Groovy,Spock,Powermock,Powermockito,第一次来,如果我错过了什么,请道歉。 我希望使用Spock绕过对静态方法的调用。反馈会很好 有了groovy Mock,我想我能够通过静态调用,但没有找到它。 作为背景,我正在用遗留java改装测试。重构是被禁止的。我正在使用spock-0.7和groovy-1.8 对静态方法的调用与以下形式的实例调用链接: public class ClassUnderTest{ public void methodUnderTest(Parameter param){ //everything els

第一次来,如果我错过了什么,请道歉。 我希望使用Spock绕过对静态方法的调用。反馈会很好

有了groovy Mock,我想我能够通过静态调用,但没有找到它。 作为背景,我正在用遗留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
    }
}
但是如果我从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中失败。

Spock只能模拟Groovy中实现的静态方法。为了模拟用Java实现的静态方法,您需要使用诸如或之类的工具


PS:鉴于这些工具使用了一些深层次的技巧来实现它们的目标,我很想知道它们是否和如何与Groovy/Spock(而不是Java/JUnit)中实现的测试协同工作。

以下是我如何用Spock解决类似问题(模拟从另一个静态类调用的静态方法调用)(v1.0)和PowerMock(v1.6.4)


@PowerMockIgnore
注释是可选的,只有在与现有库发生冲突时才使用它

我在Groovy/Spock中绕过静态方法的方法是创建在实际代码中替换掉的代理类。这些代理类只返回您需要的静态方法。您只需传递在代理类中,指向要测试的类的构造函数


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

谢谢Peter。将尝试集成并让您知道您得到了答案吗?我在这里看到了一个示例:如果有人帮助,我将在Spock中使用GroovyMock更改Java代码中的静态方法,但这错误地影响了其他测试。我使用此注释修复了@LimitMetaClassChangesSee的问题我对一个类似问题的回答是,您只需将代理类传递给您正在测试的类的构造函数。这意味着什么?静态方法不是通过实例调用的,因此没有机会将源/代理类传递给测试类。是否有进一步的解释?@lebeca,对,但是如果您创建一个代理类并将其传递给在构造函数中,您可以在Groovy中模拟这些包含静态方法的代理类。例如:``ProxyForStaticMethod proxy=mock(ProxyForStaticMethod);Monster Monster=new Monster(proxy);``现在,在编写规范时,您可以通过以下方式“模拟”静态方法:
proxy.staticMethod()>>“mocked static”
这里的问题是,要测试的类不是用代理类构造的,而是用普通类构造的。我的意思是,静态类是作为一个util构建的,为了方便起见,包装它对我来说没有任何意义。你的方法似乎消除了代码中的直接静态方法调用,对吗?很抱歉,响应太晚了必须修改ested类,以便通过传入所需的代理类来包含用于测试的构造函数。静态方法确实会被实际代码调用。但是,在测试文件中,您可以阻止使用此代理的实际静态调用,并模拟它以返回任何内容。
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"

   }
}