2014-06-25 28 views
31

Cách tốt nhất để chạy thử nghiệm tích hợp (ví dụ: @IntegrationTest) với Spock là gì? Tôi muốn khởi động toàn bộ ứng dụng Spring Boot và thực hiện một số cuộc gọi HTTP để kiểm tra toàn bộ chức năng.Kiểm tra tích hợp với Spring Boot và Spock

tôi có thể làm điều đó với JUnit (lần đầu tiên chạy ứng dụng và sau đó kiểm tra thực hiện):

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = MyServer.class) 
@WebAppConfiguration 
@IntegrationTest 
class MyTest { 
    RestTemplate template = new TestRestTemplate(); 

    @Test 
    public void testDataRoutingWebSocketToHttp() { 
     def a = template.getForEntity("http://localhost:8080", String.class) 
     println a 
    } 
} 

Nhưng với Spock ứng dụng không khởi động:

@SpringApplicationConfiguration(classes = MyServer.class) 
@WebAppConfiguration 
@IntegrationTest 
class MyTestSpec extends Specification { 

    RestTemplate template = new TestRestTemplate(); 

    def "Do my test"() { 
     setup: 
     def a = template.getForEntity("http://localhost:8080", String.class) 

     expect: 
     println a 
    } 
} 

Đối với Spock, trong tất nhiên, tôi đã chỉ định các phụ thuộc thích hợp trong tệp xây dựng Gradle của tôi:

... 
dependencies { 
    testCompile 'org.spockframework:spock-core:0.7-groovy-2.0' 
    testCompile 'org.spockframework:spock-spring:0.7-groovy-2.0' 
} 
... 

Tôi có thiếu gì đó không?

Trả lời

43

Vấn đề là Spock Spring đang tìm kiếm chú thích @ContextConfiguration của Spring và không quản lý để tìm chú thích. Nói đúng cách MyTestSpec được chú thích với @ContextConfiguration vì đó là chú giải meta trên @SpringApplicationConfiguration nhưng Spock Spring không coi meta-chú thích là một phần của tìm kiếm của nó. Có một số issue để giải quyết giới hạn này. Trong thời gian chờ đợi, bạn có thể làm việc xung quanh nó.

Tất cả những gì @SpringApplicationConfiguration đang thực hiện là tùy chỉnh @ContextConfiguration bằng trình tải ngữ cảnh đặc thù cho Khởi động. Điều này có nghĩa rằng bạn có thể đạt được hiệu quả tương tự bằng cách sử dụng một cấu hình phù hợp @ContextConfiguration chú thích thay vì:

@ContextConfiguration(loader = SpringApplicationContextLoader.class, classes = MyServer.class) 
@WebAppConfiguration 
@IntegrationTest 
class MyTestSpec extends Specification { 
    … 
} 

Cập nhật: Chỉ cần chắc chắn rằng nó rõ ràng (và dựa trên các ý kiến, đó là không), cho điều này để làm việc bạn cần phải có org.spockframework:spock-spring trên đường dẫn lớp.

+0

Thú vị, tôi khá chắc chắn tôi đã thử trước và nó không hoạt động ... nhưng dù sao, cảm ơn! – kuceram

+0

Có một lá cờ để cung cấp VM khi chạy thử nghiệm tích hợp không? Tôi đã sao chép cấu hình này và ứng dụng của tôi không bắt đầu. Tôi có quyền suy ra rằng MyServer là lớp có chú thích Cấu hình và EnableAutoConfiguration không? – loteq

+2

Không cần cờ nào và khoản khấu trừ của bạn về MyServer là chính xác. Bạn có thể đọc thêm về @ContextConfiguration tại đây: http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/htmlsingle/#integration-testing-annotations-spring. Bạn đã có spock-spring trên classpath? –

3

Trong phiên bản mùa xuân Boot mới (1.4) thay vì sử dụng:

@SpringApplicationConfiguration(classes = MyServer.class) 
@WebAppConfiguration 
@IntegrationTest 

Bạn có thể sử dụng

@SpringBootTest(classes = MyServer.class) 

và bạn sẽ có thể bắt đầu bối cảnh ứng dụng và thiết lập bất kỳ phụ thuộc.

để biết thêm thông tin, xin vui lòng có một cái nhìn vào ví dụ này: http://ignaciosuay.com/how-to-do-integration-tests-with-spring-boot-and-spock/

4

Lý tưởng nhất là bạn sẽ sử dụng Spring Boot 1.4+ và Spock 1.1+.

Spring Boot đã thêm rất nhiều chú thích hữu ích. Ngoài ra, @SpringBootTest mà @ ignacio.suay đã đề cập, họ cũng đã thêm @TestConfiguration đó là hữu ích nếu bạn muốn sử dụng mocks Spring trong các bài kiểm tra tích hợp của bạn thay vì Mockito.

Nếu bạn kết hợp @TestConfiguration với Spock DetachedMockFactory mới, thì bạn có tất cả các thành phần bạn sẽ cần để chèn Spock Mocks vào ngữ cảnh mùa xuân của bạn.

Tôi có một bài đăng trên blog có mã mẫu ở đây: Spring Integration Testing with Spock Mocks.

Các nhanh chóng và dơ bẩn này là

@SpringBootTest 
class MyIntegrationTest extends Specification { 

    @Autowired ExternalRankingService externalRankingServiceMock 

    def "GetRank"() { 
    when: 
    classUnderTest.getRankFor('Bob') 

    then: 
    1 * externalRankingServiceMock.fetchRank('Bob') >> 5 

    } 

    @TestConfiguration 
    static class Config { 
    private DetachedMockFactory factory = new DetachedMockFactory() 

    @Bean 
    ExternalRankingService externalRankingService() { 
     factory.Mock(ExternalRankingService) 
    } 
    } 
} 

CẬP NHẬTa PR để nhận được hỗ trợ có nguồn gốc ở Spock cho tiêm Spock Mocks vào bối cảnh mùa xuân để thử nghiệm hội nhập. Mới @SpringBean@SpringSpy sẽ như @MockBean@SpyBean chú thích

+0

TestConfiguration có thể được sử dụng để xác định các hạt bổ sung hoặc tùy chỉnh cho thử nghiệm, chế nhạo chỉ là một trong nhiều trường hợp sử dụng. Bạn có thể chỉ cần sử dụng spring @MockBean để thử sử dụng Mockito .... – MariuszS

+0

@MariuszS Câu hỏi này là về Spock. Nó sẽ được coi là một mùi mã khá xấu để sử dụng Mockito kết hợp với Spock. Spock đã chế nhạo xây dựng nó. Tại thời điểm câu trả lời này, '@ MockBean' không hỗ trợ Spock Mocks. – Snekse

0

Dưới đây là một thiết lập mà khởi động Application khởi động và sau đó chạy thử nghiệm Spock:

class HelloControllerSpec extends Specification { 

@Shared 
@AutoCleanup 
ConfigurableApplicationContext context 

void setupSpec() { 
    Future future = Executors 
      .newSingleThreadExecutor().submit(
      new Callable() { 
       @Override 
       public ConfigurableApplicationContext call() throws Exception { 
        return (ConfigurableApplicationContext) SpringApplication 
          .run(Application.class) 
       } 
      }) 
    context = future.get(60, TimeUnit.SECONDS) 
} 

void "should return pong from /ping"() { 
    when: 
    ResponseEntity entity = new RestTemplate().getForEntity("http://localhost:8080/ping", String.class) 

    then: 
    entity.statusCode == HttpStatus.OK 
    entity.body == 'pong' 
} 
} 

Và hãy nhớ để thêm phụ thuộc vào Spock và groovy bên build.gradle

dependencies { 
    // other dependencies 
    testCompile "org.codehaus.groovy:groovy-all:2.2.0" 
    testCompile "org.spockframework:spock-core:0.7-groovy-2.0" 
} 
Các vấn đề liên quan