使用闭包替代Mock做测试
发布时间:2020-12-14 17:04:43 所属栏目:大数据 来源:网络整理
导读:http://groovy.codehaus.org/Developer+Testing+using+Closures+instead+of+Mocks 觉得这篇文章对mock测试不错,简单翻译一下. 在一些简单的测试场景下,可以采用闭包加"as"关键字来实现我们需要mock的对象. 这种做法针对"面向接口编程"和"依赖注入"非常有效.
http://groovy.codehaus.org/Developer+Testing+using+Closures+instead+of+Mocks
觉得这篇文章对mock测试不错,简单翻译一下. 在一些简单的测试场景下,可以采用闭包加"as"关键字来实现我们需要mock的对象. 这种做法针对"面向接口编程"和"依赖注入"非常有效. 比如有这样的接口: interface Logger { def log(message) } interface Helper { def doSomething(param) } interface Factory { Helper getInstance() } 有这样的实现类: class MyApp { private factory private logger MyApp(Factory factory,Logger logger) { this.logger = logger this.factory = factory } def doMyLogic(param) { factory.getInstance().doSomething(param) logger.log('Something done with: ' + param) } } 具体用闭包的写法: def param = 'DUMMY STRING' def logger = { message -> assert message == 'Something done with: ' + param} def helper = { assert it == param } def factory = { helper as Helper } def myApp = new MyApp(factory as Factory,logger as Logger) myApp.doMyLogic(param) 只mock一个方法相对来说比较简单,如果需要同时mock多个方法,比如这种: interface Helper { def doSomething(param) def doSomethingElse(param) } def doMyLogic(param) { def helper = factory.getInstance() helper.doSomething(param) helper.doSomethingElse(param) logger.log('Something done with: ' + param) } 对于这种情况,可以创建一个以要mock的方法为key,以闭包为value的map,然后将map as为指定的接口: def helperMethod = { assert it == param } def helper = [doSomething:helperMethod,doSomethingElse:helperMethod] // as before def factory = { helper as Helper } 如果两个方法执行同样的内容的话,其实可以这样写: def factory = { helperMethod as Helper } 延伸阅读: http://groovy.codehaus.org/Groovy+way+to+implement+interfaces 这篇文章也不错,用闭包代替接口 一个接口可以用闭包来实现: // a readable puts chars into a CharBuffer and returns the count of chars added def readable = { it.put("12 34".reverse()); 5 } as Readable // the Scanner constructor can take a Readable def s = new Scanner(readable) assert s.nextInt() == 43 对于有多个方法的这样定义: interface X { void f(); void g(int n); void h(String s,int n); } x = {Object[] args -> println "method called with $args"} as X x.f() x.g(1) x.h("hello",2) 那么接口的每一个方法被调用的时候都会执行闭包. 为了适应多个方法,闭包中的参数使用了数组 更通用的做法是用map来模拟多个方法的情况: impl = [ i: 10,hasNext: { impl.i > 0 },next: { impl.i-- },] iter = impl as Iterator while ( iter.hasNext() ) println iter.next() 如果指定的方法为在map中没有对应的key,那么会抛空指针异常 interface X { void f(); void g(int n); void h(String s,int n); } x = [ f: {println "f called"} ] as X x.f() //x.g() // NPE here 下面是一种错误的写法: x = { f: {println "f called"} } as X x.f() x.g(1) 因为这个是定义了一个闭包而不是一个map,而且从groovy的语法来说也是不允许的. 更多的as用法,可以看这里( http://johnnyjian.iteye.com/blog/160796) 这里有一点需要注意,as的class类型必须是一个静态的引用,否则是失败,但是了动态指定as的具体类型,也可以使用asType这样写: def loggerInterface = Class.forName( 'my.LoggerInterface' ) def logger = [ log : { Object[] params -> println "LOG: ${params[0]}"; if( params.length > 1 ) params[1].printStackTrace() },close : { println "logger.close called" } ].asType( loggerInterface ) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |