2014-12-12 13 views
11

Đưa ra những điều sau đây, làm cách nào để giả sử processMessage() sử dụng Spock, để tôi có thể kiểm tra processBulkMessage() gọi processMessage() n lần, trong đó n là số lượng thư trong BulkMessage?Grails/Spock: Làm thế nào để thử phương thức đơn trong lớp mà phương thức được gọi từ bên trong lớp đó?

class BulkMessage { 
    List messages 
} 

class MyService { 

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

    def processMessage(Message message) { 

    } 
} 

Trả lời

5

Bạn có thể sử dụng spies và phần mocks (yêu cầu Spock 0.7 hoặc mới hơn).

Sau khi tạo một gián điệp, bạn có thể nghe ở trên nói chuyện giữa người gọi và đối tượng thực là cơ sở để gián điệp:

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

Đôi khi, đó là mong muốn cả hai thực hiện một số mã và đại biểu đến phương pháp thực tế:

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

Nó không sử dụng Spock built-in Mocking API (không chắc chắn làm thế nào để một phần nhạo báng một đối tượng), nhưng điều này nên làm như lừa:

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

tôi n ý kiến ​​của tôi đây không phải là một giải pháp được thiết kế tốt. Kiểm tra và thiết kế đi bộ trong tay - Tôi khuyên bạn nên this nói chuyện để điều tra nó tốt hơn. Nếu có nhu cầu kiểm tra xem phương thức khác đã được viện dẫn trên một đối tượng đang được thử nghiệm thì có vẻ như nó phải được chuyển đến đối tượng khác với trách nhiệm khác.

Đây là cách tôi sẽ thực hiện. Tôi biết làm thế nào khả năng hiển thị hoạt động trong groovy để tâm ý kiến.

@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

Cảm ơn rất nhiều - Tôi vừa mới xem xét lại này và đã học được rất nhiều về thiết kế kể từ khi tôi đặt câu hỏi. Bây giờ tôi đồng ý với bạn rằng thiết kế tốt hơn sẽ là một bulkMessageProcessingService và một individualMessageProcessingService. Do đó, thử nghiệm là tầm thường với một mô hình. – John

1

Đối với Java Xuân folks thử nghiệm trong Spock:

constructorArgs là con đường để đi, nhưng sử dụng constructor tiêm. Spy() sẽ không cho phép bạn thiết lập các trường tự động trực tiếp.

// **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 trống phương pháp trên Spy đối tượng

// **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: 
      ... 
    } 
} 
Các vấn đề liên quan