Groovy MockFor: как избежать вложенных замыканий при использовании нескольких макетов? - PullRequest
4 голосов
/ 26 апреля 2019

У меня есть три класса:

class B1 {
    def performB1(){}
}

class B2 {
    def performB2(){}
}

class A {
    private B1 b1
    private B2 b2

    A(b1, b2){
        this.b1 = b1
        this.b2 = b2
    }

    def perfromA(){
        b1.performB1()
        b2.performB2()
    }
}

Я хочу проверить метод performA в классе A.Поэтому я создал макеты для классов B1 и B2.Вот мой класс:

import groovy.mock.interceptor.MockFor;

 class ATest  extends GroovyTestCase {
     private MockFor b1Mock
     private MockFor b2Mock

    void setUp() {
        b1Mock = new MockFor(B1)
        b2Mock = new MockFor(B2)
    }


    void testIsEnoughSpaceOnArtifactory_failedToGetQuotaFromArtifactory(){
        b1Mock.demand.with {
            performB1 { println "Performing B1" }
        }

        b2Mock.demand.with {
            performB2 {println "Performing B2"}
        }

        b2Mock.use {
           b1Mock.use {
               def a = new A(new B1(), new B2())
               a.perfromA()
           }
        }
    }
}

Хорошо работает - я это проверил.Он основан на этом вопросе .

Однако предположим, что у меня есть класс с тремя зависимостями.Это все еще чистый код.Требуется 3 издевательства.Код будет выглядеть так:

b3Mock.use { 
    b2Mock.use {
        b1Mock.use {
            def a = new A(new B1(), new B2(), new B3())
            a.perfromA()
        }
    }
}

Это выглядит нелепо и далеко не чисто.Представьте, что мне не удалось достичь цели не более 3-х зависимостей.Тогда мои тесты будут выглядеть еще смешнее.Есть ли способ проверки вызовов на макетах без вложенных замыканий?Я мог бы использовать что-то подобное (см. здесь для справки):

b1Mock.use { 
    def a = new A(new B1(), b2Mock.proxyInstance(), b3Mock.proxyInstance())
    a.perfromA()
}
b2Mock.expect.verify()
b3Mock.expect.verify()

К сожалению, когда я запускаю его, я получаю следующую ошибку:

java.lang.NullPointerException: Невозможно вызвать метод executeB2 () для нулевого объекта

Можно ли использовать несколько макетов в groovy без вложенных замыканий, чтобы иметь чистый код?

1 Ответ

3 голосов
/ 14 мая 2019

следующий скрипт работает нормально:

import groovy.mock.interceptor.MockFor
//------ CLASSES
class B1 { def performB1(){} }
class B2 { def performB2(){} }
class B3 { def performB3(){} }

class A {
    private B1 b1
    private B2 b2
    private B3 b3

    A(b1, b2, b3){
        this.b1 = b1
        this.b2 = b2
        this.b3 = b3
    }

    def perfromA(){
        b1.performB1()
        b2.performB2()
        b3.performB3()
    }
}
//------ TESTS
def b1Mock = new MockFor(B1)
def b2Mock = new MockFor(B2)
def b3Mock = new MockFor(B3)

b1Mock.demand.with {
    performB1 { println "Performing B1" }
}
b2Mock.demand.with {
    performB2 {println "Performing B2"}
}
b3Mock.demand.with {
    performB3 {println "Performing B3"}
}

def b2inst = b2Mock.proxyInstance()
def b3inst = b3Mock.proxyInstance()
b1Mock.use { 
    def a = new A(new B1(), b2inst, b3inst)
    a.perfromA()
}
b2Mock.verify(b2inst)
b3Mock.verify(b3inst)

и со следующей функцией

def useAll(List<MockFor> mocks,Closure test){
    Closure use4all = mocks.inject(test){ Closure testX, next-> 
        return { next.use(testX) } 
    }
    use4all.call()
}

возможно свести к минимуму вложенные замыкания использования к этому:

useAll([b1Mock,b2Mock,b3Mock]){
    def a = new A(new B1(), new B2(), new B3())
    a.perfromA()
}
...