在 Junit 中测试匿名 class 或 Groovy/Spock 测试

Test anonymous class in Junit or Groovy/Spock test

我正在尝试在 Groovy/Spock 中编写单元测试并且必须测试以下代码。

public class ClassA {
    @Inject
    private ClassB classB;

    @Inject
    private ClassC classC;

    @Inject
    private ClassD classD;

    public void update(final int a, final Map<String, Object> b) {
        classB.executeCommand(classC.callToMethodInClassC(), new InterfaceE<Void>() {
            @Override
            public Void execute() {
                classD.update(a, b);
                return null;
            }
        });
    }
}

现在,当我编写测试代码时,我无法到达 classD.update(a, b); 行。我知道如何为 ClassB、ClassC、ClassD 注入 mocks/real 对象,但无法达到该语句。请帮忙。

注: ClassA.update() & ClassD.update()除了签名匹配外没有任何关系

像这样模拟您的 classB:

Mock(ClassB) {
    executeCommand(_, _) >> { c, e -> e.execute() }
}

即为 ClassB 的 executeCommand 方法提供一个模拟实现,它实际调用接口 E 的 execute 方法。

编辑:完整的工作示例:

import spock.lang.Specification

class TestMeSpec extends Specification {

    def "my test"() {
        def b = Mock( ClassB ) {
            executeCommand( _, _ ) >> { c, e -> e.execute() }
        }
        def c = Mock( ClassC )
        def d = Mock( ClassD )

        def a = new ClassA( classB: b, classC: c, classD: d )

        when:
        a.update( 0, [ : ] )

        then:
        1 * d.update( 0, [ : ] )
    }
}

class ClassA {
    ClassB classB
    ClassC classC
    ClassD classD

    void update( final int a, final Map<String, Object> b ) {
        classB.executeCommand( classC.callToMethodInClassC(), new InterfaceE<Void>() {
            @Override
            Void execute() {
                classD.update( a, b )
            }
        } )
    }
}

class ClassB {
    void executeCommand( c, InterfaceE e ) {
        println "REAL CLASS B executCommand() METHOD RUNNING"
    }
}

class ClassC {
    def callToMethodInClassC() {}
}

class ClassD {
    void update( a, b ) {
        println "REAL CLASS D update() method called with $a and $b"
    }
}

interface InterfaceE<T> {
    T execute()
}