2014-12-12 19 views
11

W związku z tym, w jaki sposób kpić processMessage() przy użyciu Spock, tak aby można sprawdzić, że processBulkMessage() wywołania processMessage() n razy, gdzie n jest liczbą wiadomości w BulkMessage?Grails/Spock: Jak wyśmiewać pojedynczą metodę w klasie, w której metoda jest wywoływana z samej klasy?

class BulkMessage { 
    List messages 
} 

class MyService { 

    def processBulkMessage(BulkMessage msg) { 
     msg.messages.each {subMsg-> 
      processMessage(subMsg) 
     } 
    } 

    def processMessage(Message message) { 

    } 
} 

Odpowiedz

5

Można użyć spies i częściowe mocks (wymaga Spocka 0.7 lub nowszego).

Po utworzeniu szpiega można podsłuchiwać rozmowy między rozmówcą i rzeczywistego obiektu bazowego szpiega:

def subscriber = Spy(SubscriberImpl, constructorArgs: ["Fred"]) 
subscriber.receive(_) >> "ok" 

Czasami pożądane jest, aby zarówno wykonać jakiś kod i delegować do rzeczywistego sposobu:

subscriber.receive(_) >> { String message -> callRealMethod(); message.size() > 3 ? "ok" : "fail" } 
1

Nie używa Spock wbudowaną Mocking API (nie wiem, jak częściowo mock obiektu), ale to powinno wystarczyć:

class FooSpec extends Specification { 

    void "Test message processing"() { 
     given: "A Bulk Message" 
     BulkMessage bulk = new BulkMessage(messages: ['a', 'b', 'c']) 

     when: "Service is called" 
     def processMessageCount = 0 
     MyService.metaClass.processMessage { message -> processMessageCount++ } 
     def service = new MyService() 
     service.processBulkMessage(bulk) 

     then: "Each message is processed separately" 
     processMessageCount == bulk.messages.size() 
    } 
} 
2

i W mojej opinii nie jest to dobrze zaprojektowane rozwiązanie. Testy i projektowanie idą w parze - polecam rozmowę, aby lepiej to zbadać. Jeśli istnieje potrzeba sprawdzenia, czy inna metoda została wywołana na testowanym obiekcie, wydaje się, że powinna zostać przeniesiona do innego obiektu z inną odpowiedzialnością.

Oto, jak bym to zrobił. Wiem, jak widoczność działa świetnie, więc pamiętaj o komentarzach.

@Grab('org.spockframework:spock-core:0.7-groovy-2.0') 
@Grab('cglib:cglib-nodep:3.1') 

import spock.lang.* 

class MessageServiceSpec extends Specification { 

    def 'test'() { 
     given: 
     def service = new MessageService() 
     def sender = GroovyMock(MessageSender) 

     and: 
     service.sender = sender 

     when: 
     service.sendMessages(['1','2','3']) 

     then: 
     3 * sender.sendMessage(_) 
    } 
} 
class MessageSender { //package access - low level 
    def sendMessage(String message) { 
     //whatever 
    } 
} 

class MessageService { 

    MessageSender sender //package access - low level 

    def sendMessages(Iterable<String> messages) { 
     messages.each { m -> sender.sendMessage(m) } 
    } 
} 
+0

Dzięki bardzo - Właśnie powrócił to i nauczyliśmy się wiele o projektowaniu od zadałem pytanie. Zgadzam się z tobą, że lepszym projektem będzie usługa bulkMessageProcessingService i individualMessageProcessingService. Testowanie jest zatem trywialne z pozorowaniem. – John

1

Java Wiosna ludzie testów w Spocka:

constructorArgs jest droga, ale używać zastrzyk konstruktora. Spy() nie zezwoli ci na bezpośrednie ustawianie pól autowych.

// **Java Spring** 
class A { 
    private ARepository aRepository; 

    @Autowire 
    public A(aRepository aRepository){ 
     this.aRepository = aRepository; 
    } 

    public String getOne(String id) { 
     tryStubMe(id) // STUBBED. WILL RETURN "XXX" 
     ... 
    } 

    public String tryStubMe(String id) { 
     return aRepository.findOne(id) 
    } 

    public void tryStubVoid(String id) { 
     aRepository.findOne(id) 
    } 
} 

// **Groovy Spock** 
class ATest extends Specification { 

    def 'lets stub that sucker' { 
     setup: 
      ARepository aRepository = Mock() 
      A a = Spy(A, constructorArgs: [aRepository]) 
     when: 
      a.getOne() 
     then: 
      // Stub tryStubMe() on a spy 
      // Make it return "XXX" 
      // Verify it was called once 
      1 * a.tryStubMe("1") >> "XXX" 
    } 
}  

Spock - stubbing void metody na Spy sprzeciw

// **Groovy Spock** 
class ATest extends Specification { 

    def 'lets stub that sucker' { 
     setup: 
      ARepository aRepository = Mock() 
      A a = Spy(A, constructorArgs: [aRepository]) { 
       1 * tryStubVoid(_) >> {} 
      } 
     when: 
      ... 
     then: 
      ... 
    } 
}