我正在尝试使用redis-3.2.4 $ rdb -c memory dump.rdb -k my.*
database,type,key,size_in_bytes,encoding,num_elements,len_largest_element
0,list,"mylistkey",219,quicklist,7,6
0,sortedset,"mysortedsetkey",143,ziplist,6,5
0,hash,"myhashkey",115,ziplist,2,6
0,string,"mystringkey",88,string,13,13
0,string,"myhllkey",168,string,90,90
0,set,"mysetkey",452,hashtable,4,6
进行一些单元测试。我想断言,确实以某些特定值作为参数调用了函数。我找不到方法。有帮助吗?
这是它的样子:
redis-3.2.4 $ rdb -c memory dump.rdb -k my.* -f memory.csv
redis-3.2.4 $ head memory.csv
database,type,key,size_in_bytes,encoding,num_elements,len_largest_element
0,list,"mylistkey",219,quicklist,7,6
0,sortedset,"mysortedsetkey",143,ziplist,6,5
0,hash,"myhashkey",115,ziplist,2,6
0,string,"mystringkey",88,string,13,13
0,string,"myhllkey",168,string,90,90
0,set,"mysetkey",452,hashtable,4,6
答案 0 :(得分:0)
MockFor
类无法实现预期的行为。忽略main
方法有一个重要的效果-内部方法myFunction
被执行,但是它在没有MockInterceptor
的情况下发生。您可以在groovy.mock.MockProxyMetaClass
的开头的invokeMethod
类中放置一个断点(第74行),然后运行调试器以查看会发生什么。
public Object invokeMethod(final Object object, final String methodName, final Object[] arguments) {
if (null == interceptor && !fallingThrough) {
throw new RuntimeException("cannot invoke method '" + methodName + "' without interceptor");
}
Object result = FALL_THROUGH_MARKER;
if (interceptor != null) {
result = interceptor.beforeInvoke(object, methodName, arguments);
}
if (result == FALL_THROUGH_MARKER) {
Interceptor saved = interceptor;
interceptor = null;
boolean savedFallingThrough = fallingThrough;
fallingThrough = true;
result = adaptee.invokeMethod(object, methodName, arguments);
fallingThrough = savedFallingThrough;
interceptor = saved;
}
return result;
}
在foo.main()
块中调用mock.use {}
方法可为非null拦截器调用此方法。 interceptor.beforeInvoke()
返回的结果等于FALL_THROUGH_MARKER
,因为main
方法被标记为已忽略。在这种情况下,拦截器会暂时设置为null
,并且该方法会以常规方式调用-它会调用内部myFunction
方法,但是由于null
拦截器目前尚未记录此事实。
基本上,您将测试用例中的模拟对象视为模拟对象,而不是模拟对象。 Groovy标准模拟库不支持间谍对象,但您可以使用例如Spock Framework使用间谍对象编写测试。使用Spock,您在问题中显示的测试可能看起来像这样:
import spock.lang.Specification
class ExampleSpec extends Specification {
static class MyClass {
def main() {
return myFunction(0, 0 ,0)
}
def myFunction(def a, def b, def c) {
return '2'
}
}
def "should call myFunction with specific parameters"() {
given:
def foo = Spy(MyClass)
when:
foo.main()
then:
1 * foo.myFunction(0, 0, 0)
and:
0 * foo.myFunction(1,0,0)
}
}
它执行一个真实的foo.main()
方法,但是它模拟foo.myFunction()
方法并记录调用并测试该方法是否被正确的参数调用-它记录它被参数{{1}调用一次},并且未使用参数(0, 0, 0)
调用它。
重要提示:如果您是从类而非接口创建模拟/间谍对象,则需要将(1, 0, 0)
依赖项与Spock一起添加。
答案 1 :(得分:0)
好的,这是可行的,因为mock.demand.myFunction
采用普通的Closure
。
我最终得到了这样的东西:
import groovy.mock.interceptor.MockFor
import org.junit.Test
class MyClassTest extends GroovyTestCase {
@Test
void test_correctness_of_passed_arguments() {
def mock = new MockFor(MyClass)
mock.ignore('main')
def res = []
// the mocked function stores its values in `res` and returns '0'
mock.demand.myFunction(4) {a, b, c ->
res.add([a, b, c])
'0'
}
mock.use {
def foo = new MyClass()
foo.main() // <--- this is in there that it gets executed
}
mock.expect.verify()
res[0] // <--- I can then access the values there
}
}
在上面的示例中,我请求myFunction
次被调用4
。