写点什么

Groovy 动态添加方法和属性及 Spock 单测

用户头像
FunTester
关注
发布于: 刚刚

在最近的一边学习一边复习的过程中,发现了很多有意思的事情。今天就分享一个groovy.lang.MetaClass应用:如何运行中,动态给类和对象增加属性和添加方法。


对于 Java、Groovy 来讲,如果用到一个类,那么这个类的属性和方法已经是固定的,可是随着我的学习,发现这个常识并不靠谱。下面开始我的表演。

添加对象方法

下面是简化的语法object.metaClass.object_method = {闭包},如下:


        def funTester = new FunTester()        funTester.metaClass.test = {            logger.info("我是测试方法:{}","test")        }        funTester.test()
复制代码


控制台输出:


INFO-> main 当前用户:oker,工作目录:/Users/oker/IdeaProjects/funtester/,系统编码格式:UTF-8,系统Mac OS X版本:10.16INFO-> main 我是测试方法:test
Process finished with exit code 0
复制代码

添加静态方法

下面是简化的语法object.metaClass.static.object_method = {闭包},如下:


        def funTester = new FunTester()        funTester.metaClass.test = {            logger.info("我是测试方法:{}","static.test")        }        funTester.test()
复制代码


控制台输出:


INFO-> main 当前用户:oker,工作目录:/Users/oker/IdeaProjects/funtester/,系统编码格式:UTF-8,系统Mac OS X版本:10.16INFO-> main 我是测试方法:static.test
Process finished with exit code 0
复制代码

添加属性

        funTester.metaClass.setProperty("name","FunTester")        logger.info(funTester.getProperty("name"))
复制代码


控制台输出:


INFO-> main 当前用户:oker,工作目录:/Users/oker/IdeaProjects/funtester/,系统编码格式:UTF-8,系统Mac OS X版本:10.16INFO-> main FunTester
Process finished with exit code 0
复制代码


FunTester 类代码:


    private static class FunTester {
}
复制代码

Spock 单元测试

下面使用 Spock 单元测试框架进行测试,有兴趣的可以看看之前的文章:



代码如下:


package com.funtest.spock

import org.apache.logging.log4j.LogManagerimport org.apache.logging.log4j.Loggerimport spock.lang.Shared
class Mop extends spock.lang.Specification {
@Shared private static final Logger logger = LogManager.getLogger(Mop.class);
def setup() { logger.info("测试方法开始了") }
def cleanup() { logger.info("测试方法结束了") }
def setupSpec() { fun.metaClass.getName() { def property = fun.getProperty("name") logger.warn("获取" + property) return property } fun.metaClass.setName = {x -> logger.warn("设置" + x) fun.metaClass.setProperty("name", x) return fun.getName() } logger.info("测试类[${getClass().getName()}]开始了") }
def cleanupSpec() { logger.info("测试类[${getClass().getName()}]结束了") }

@Shared def fun = new Mop()
def "测试动态添加对象方法"() { given: fun.metaClass.ob_method = {return 12} expect: 12 == fun.ob_method() }

def "测试动态添加静态方法"() { given: Mop.metaClass.static.clas_method = {return 12} expect: 12 == Mop.clas_method() }
def "测试动态添加获取属性"() { expect: fun.setName(name) == tt
where: name | tt "FunTester" | "FunTester" "Have Fun" | "Have Fun" }
}
复制代码


控制台输出:



> Task :test FAILEDINFO-> Test worker 测试类[com.funtest.spock.Mop]开始了INFO-> Test worker 测试方法开始了INFO-> Test worker 测试方法结束了INFO-> Test worker 测试方法开始了INFO-> Test worker 测试方法结束了INFO-> Test worker 测试方法开始了WARN-> Test worker 设置FunTesterWARN-> Test worker 获取FunTesterINFO-> Test worker 测试方法结束了INFO-> Test worker 测试方法开始了WARN-> Test worker 设置Have FunWARN-> Test worker 获取FunTesterINFO-> Test worker 测试方法结束了
Condition not satisfied:
fun.setName(name) == tt| | | | || | | | Have Fun| | | false| | | 8 differences (11% similarity)| | | (FunT)e(ster)| | | (Hav-)e( Fun)| | Have Fun| FunTester<com.funtest.spock.Mop@49013545 $spock_sharedField_fun=null specificationContext=org.spockframework.runtime.SpecificationContext@6c68765>
at com.funtest.spock.Mop.测试动态添加获取属性(Mop.groovy:60)

INFO-> Test worker 测试类[com.funtest.spock.Mop]结束了
Mop > 测试动态添加对象方法 PASSEDMop > 测试动态添加静态方法 PASSEDMop > 测试动态添加获取属性 > com.funtest.spock.Mop.测试动态添加获取属性 [name: FunTester, tt: FunTester, #0] PASSEDMop > 测试动态添加获取属性 > com.funtest.spock.Mop.测试动态添加获取属性 [name: Have Fun, tt: Have Fun, #1] FAILED org.spockframework.runtime.SpockComparisonFailure at Mop.groovy:60Mop > 测试动态添加获取属性 FAILED5 tests completed, 2 failedFAILURE: Build failed with an exception.4 actionable tasks: 1 executed, 3 up-to-date
复制代码

Have Fun ~ Tester !

发布于: 刚刚阅读数: 2
用户头像

FunTester

关注

公众号:FunTester,650+原创,欢迎关注 2020.10.20 加入

Have Fun,Tester! 公众号FunTester,坚持原创文章的测试人。 FunTester测试框架作者,DCS_FunTester分布式性能测试框架作者。

评论

发布
暂无评论
Groovy动态添加方法和属性及Spock单测