3

我的测试方法中有一个带有 JMock 期望的以下片段:

context.checking(new Expectations() {{
    allowing(listener).tableChanged(with(anyInsertionEvent()));
    oneOf(listener).tableChanged(with(aRowChangedEvent(0)));
}});

在哪里anyInsertionEventaRowChangedEventAs返回Matcher<TableModelEvent>. 这摘自“由测试引导的面向对象的软件增长”一书(第 181 页)。

我尝试将此测试转换为 Groovy,但我需要的方法是:

org.jmock.Expectations.with(org.hamcrest.Matcher<T>)

被以下阴影遮蔽:

org.codehaus.groovy.runtime.DefaultGroovyMethods.with(java.lang.Object, 
    groovy.lang.Closure<T>)

结果,我在测试期间遇到错误,例如:

groovy.lang.MissingMethodException: No signature of method: $Proxy8.tableChanged() is     applicable for argument types: (java.lang.Boolean) values: [false]
Possible solutions: tableChanged(javax.swing.event.TableModelEvent)
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55)
    at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:46)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at org.rorick.auctionsniper.ui.SnipersTableModelTest$1.<init>(SnipersTableModelTest.groovy:43)
    at org.rorick.auctionsniper.ui.SnipersTableModelTest.setSniperValuesInColumns(SnipersTableModelTest.groovy:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
    at org.jmock.integration.junit4.JMock$1.invoke(JMock.java:37)
    at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:105)
    at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94)
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
    at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:98)
    at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:61)
    at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:54)
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
    at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:52)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:76)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

我怎样才能使用适当的with方法?或者,请建议任何其他方法来解决此问题。

更新:它不是阴影。Expectations.with(Matcher<Boolean>)因此,实际调用的方法是false堆栈跟踪中的值。因此,方法被错误地分派。有什么想法吗?

更新:匹配器方法如下:

public Matcher<TableModelEvent> anyInsertionEvent() {
    Matcher<Integer> insertMatcher = equalTo(TableModelEvent.INSERT);
    return new FeatureMatcher<TableModelEvent, Integer>(insertMatcher, "is an insertion event", "event type") {
        @Override
        protected Integer featureValueOf(TableModelEvent actual) {
            return actual.getType();
        }
    };
}

private Matcher<TableModelEvent> aRowChangedEvent(int row) {
    return samePropertyValuesAs(new TableModelEvent(model, row));
}
4

1 回答 1

1

最后,我找到了解决方法。请参阅下面的检查代码。new Expectations() {{}}Java 语法已经消失,取而代之的是闭包:

context.checking {
    allowing(listener).tableChanged(argThat(anyInsertionEvent()));
    oneOf(listener).tableChanged(argThat(aRowChangedEvent(0)));
}

请注意,with替换为argThat(仿照 Mockito)。context不是org.jmock.integration.junit4.JUnit4Mockery原来的实例,而是以下类的实例:

class JUnit4GroovyMockery extends JUnit4Mockery {
    public void checking(Closure c) {
         ClosureExpectations expectations = new ClosureExpectations();
         expectations.closureInit(c, expectations);
         super.checking(expectations);
    }

    private static class ClosureExpectations extends Expectations {
        void closureInit(Closure cl, Object delegate) {
            cl.setDelegate(delegate);
            cl.call();
        }

        public Object argThat(Matcher<?> matcher) {
            currentBuilder().addParameterMatcher(matcher);
            return null;
        }
    }
}

这是基于来自http://docs.codehaus.org/display/GROOVY/Using+JMock+with+Groovy的 JUnit4GroovyMockery 类。是从和argThat复制粘贴的。Expectations.with(Matcher<T>)Expectations.addParameterMatcher(Matcher<?>)

这对我有用,虽然我对这个解决方案不太满意;我更愿意保留with该方法的名称。

于 2012-09-05T21:56:56.573 回答