Spock framework Mock static resource experience summary

As mentioned earlier Spock framework Mock object, method and experience summary Today, I would like to share the summary of practical experience of Mock static resources in Spock framework. It is divided into "static resources" and "mixed scenes".

Static resources

Static variable

This usage scenario is rare. If you need Mock, you can directly assign the object of Mock to static resources. So this scene pass es.

Static method

Mock static method we use the scheme of PowerMock combined with Mockito. First, add the following notes to the test class:

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(Sputnik.class)
@PrepareForTest([NewUtil.class, HttpBase.class])
@PowerMockIgnore(["javax.management.*"])
@SuppressStaticInitializationFor(["com.funtester.util.NewUtil", "com.funtester.util.HttpBase"])

@The contents of the RunWith and @ PowerMockRunnerDelegate annotations need not be changed, but can be copied directly. The classes behind the @ PrepareForTest annotation are the classes that need to be mocked@ PowerMockIgnore this annotation is used to ignore some checks and exceptions@ SuppressStaticInitializationFor this annotation handles class initialization. This annotation is followed by the package path of the class that does not need to be initialized. In current practice, it is usually consistent with the class after @ PrepareForTest.

Secondly, we need to Mock this class in the class initialization code. The syntax is as follows:

        PowerMockito.mockStatic(HttpBase.class)
        PowerMockito.mockStatic(NewUtil.class)

Here's how to customize the behavior of static methods:

        PowerMockito.when(HttpBase.fetchServiceNames()).thenReturn(["service-prod", "api-pro", "prod", "service-prd", "write-pro"])

Define static method behavior and non static method behavior, which are consistent in syntax,

Mixed scene

When a test case requires both Mock static methods and Mock object methods, the capabilities provided by PowerMock must be used. The reason mentioned earlier is mainly because after adding class annotations, the functions of Mock objects and definition methods of Spock and Mockito will not run. No specific documents can be found to distinguish them. Therefore, in case of mixed scenarios, it is recommended to use PowerMock to Mock objects.

In terms of syntax, PowerMock mixes the syntax of dealing with static and non static resources and behavior simulation. The Demo is as follows:

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(Sputnik.class)
@PrepareForTest([NewUtil.class, HttpBase.class])
@PowerMockIgnore(["javax.management.*"])
@SuppressStaticInitializationFor(["com.funtester.util.newinterface.NewUtil", "com.funtester.util.slowapi.HttpBase"])
class TaskScheduledTest extends Specification {

    @Shared
    def service = PowerMockito.mock(IService)

    def drive = new TaskScheduled(IService: service, cid: "")

    def setupSpec() {
        PowerMockito.mockStatic(HttpBase.class)
        PowerMockito.mockStatic(NewUtil.class)
        PowerMockito.when(HttpBase.fetch()).thenReturn(["ood", "ero"])
        Mockito.when(newutil.filter(Mockito.any())).thenReturn(true)
        Mockito.when(newser.selectAll()).thenReturn([new NewInterface() {

            {
                setUrl("/abc")
                setNname("test")
                setMethod("GET")
            }
        }, new NewInterface() {

            {
                setUrl("/abcd")
                setNname("test")
                setMethod("POST")
            }
        }, new NewInterface() {

            {
                setUrl("/abce")
                setNname("test")
                setMethod("GET")
            }
        }])
        //This is because this static method is used in the send method
        PowerMockito.when(NewUtil.getsAll(anyList(), anyBoolean())).thenReturn([new NewInterface() {

            {
                setUrl("/abc")
                setNname("test")
                setMethod("GET")
            }
        }, new NewInterface() {

            {
                setUrl("/abc")
                setNname("test")
                setMethod("GET")
            }
        }])
    }

    def "Send"() {
        given:
        drive.send()

    }

    def "day"() {
    }
}

PS: in the mochito inline, which is a dependency of the higher version of mochito, it also supports the Mock of static classes and static methods, but it is extremely difficult to use in Spock. According to the data, it is caused by the inconsistency between the Spock version in the project pom and the mochito version. After trying several combinations, it still cannot be solved. Another person said that it is also related to the version that Groovy depends on, which directly breaks the defense, Abandoned the plan.

Added by anwoke8204 on Wed, 09 Feb 2022 08:21:04 +0200