简体   繁体   English

如何模拟在脚本中使用的groovy类?

[英]How to mock groovy class that is used in script?

I have some generator classes, that are used in my custom steps in Jenkins Pipeline. 我有一些生成器类,这些类在Jenkins Pipeline的自定义步骤中使用。 I would like to test those steps (which are groovy scripts), together with mocking classes that are used inside. 我想测试这些步骤(它们是普通的脚本),以及内部使用的模拟类。 While testing scripts is not a problem, mocking classes that are used inside is problematic. 尽管测试脚本不是问题,但内部使用的模拟类却有问题。

I've tried to use Mockito to mock script members, but any of ways I tried didn't worked out. 我尝试使用Mockito模拟脚本成员,但是我尝试的任何方法均未解决。 I have found solutions to mock function or property inside script method, but not class object. 我在脚本方法中找到了模拟函数或属性的解决方案,但没有找到类对象的解决方案。

So this is (simplified) script. 因此,这是(简体)脚本。 It uses Class that acts as XML generator. 它使用充当XML生成器的Class。

// XmlGenerator is custom class that makes some magic
// script is named myCustomStep.groovy
def call(def val) {
    def myXmlGenerator = new XmlGenerator()
    xmlGenerator.setValue(val)
    def xmlString = xmlGenerator.generate()
    writeFile file: "/some/file/path.xml", text: xmlString
}

I have no problems with mocking "writeFile" or "sh", but I would like to mock XmlGenerator.generate() method, something like 我模拟“ writeFile”或“ sh”没有问题,但我想模拟XmlGenerator.generate()方法,类似

@Test
void someTest() {
    def myCustomStep = loadscript("vars/myCustomStep.groovy")
    def generatorMockedMethod = mock(Function)
    myCustomStep.metaclass.myXmlGenerator.generate = generatorMockedMethod.&apply // Just my imagination of how I would like it to be
    helper.registerAllowedMethod("writeFile", [Map.class], { params ->
        println "File was saved: file: ${params.file}, text: ${params.text}"
    })

    myCustomStep val: "50"
    assert generatorMockedMethod.called(1)

I managed to do that with Groovy build-in mocking mechanism 我设法通过Groovy内置的模拟机制做到了这一点

Script to be tested: 要测试的脚本:

    // XmlGenerator is custom class that makes some magic
    // script is named myCustomStep.groovy
    def call(def val) {
        def myXmlGenerator = new XmlGenerator()
        xmlGenerator.setValue(val)
        def xmlString = xmlGenerator.generate()
        writeFile file: "/some/file/path.xml", text: xmlString
    }

And the test itself 测试本身

    @Test
    void someTest() {
        def myCustomStep = loadscript("vars/myCustomStep.groovy")

        def  xmlGenMock = StubFor(XmlGenerator)
        xmlGenMock.demand.with {
            setValue { }
            generate { "<?xml><\xml> "} // Name of method to mock, and value to be returned when called
        }

        helper.registerAllowedMethod("writeFile", [Map.class], { params ->
            println "File was saved: file: ${params.file}, text: ${params.text}"
        })

        xmlGenMock.use {
            myCustomStep val: "50"
        }

        xmlGenMock.verify()
    }

Trick here is "stub.use" method. 这里的技巧是“ stub.use”方法。 Inside that closure, all instancess of stubed class will be relaced with stubbed version. 在该闭包内部,存根类的所有实例都将被存根版本取代。 If you want to mock/stub more that one class, just put one closure inside another like: 如果要模拟/存根更多的一个类,只需将一个闭包放在另一个内,例如:

    def stubOne = StubFor(MyClassOne)
    def stubTwo = StubFor(MyClassTwo)

    stubOne.use {
        stubTwo.use {
            // Call to be tested 
        }    
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM