Статьи

Интеграционное тестирование Grails 3.3

Spock Framework, поставляемый с Grails, легко использовать для насмешки или оцепления соавтора (например, службы) в наших модульных тестах Grails.

В главе « Тестирование» объясняется немного о том, как насмехаться над соавторами, doWithSpring doWithConfig обратного вызова doWithSpring / doWithConfig , аннотации FreshRuntime для FreshRuntime в тестах, но в основном они предназначены для модульного тестирования .

Как насчет насмешивания бобов в интеграционном тесте?

пример

Что делать, если у нас есть контроллер

01
02
03
04
05
06
07
08
09
10
11
12
13
14
class AnimalRegistrationController {
    AnimalRegistrationService animalRegistrationService
 
    def arrival(ArrivalCommand arrival) {
 
        animalRegistrationService
            .registerArrival(arrival)
            .map { ArrivalErrorMessage aem ->
                renderErrors(aem)
            }.orElse {
                render status: 200
            }
    }
}

который вызывает сервис, который вызывает репозиторий — который может делать внешние вызовы, которые вы не хотите делать в интеграционном тесте.

1
2
3
4
5
6
7
8
class AnimalRegistrationService {
    ArrivalRepository arrivalRepository
 
    Optional registerArrival(Arrival arrival) {
        arrivalRepository.registerArrival(arrival)
    }
 
}

Ранее я писал, что в Grails 3.3 есть Spock 1.1, который дал нам несколько новых возможностей, таких как ответ по умолчанию для java.util.Optional … но он дал нам больше !

1. DetachedMockFactory и TestConfiguration

Теперь у нас также есть DetachedMockFactory, который мы можем использовать для объявления имитаций вне иерархии вне Specification , например, в конфигурации Spring.

Я был вызван этой статьей о тестировании Spring Integration и настроил его для работы с Grails 3.3 — который основан на Spring Boot, но не совсем использует все аннотации Spring, которые мы использовали в ванильном приложении Spring.

Поэтому мы создаем конфигурацию, специально для тестирования, в src/test/groovy используя DetachedMockFactory например

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
import spock.mock.DetachedMockFactory
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
...
 
@TestConfiguration
class TestRepositoryConfig {
 
    private DetachedMockFactory factory = new DetachedMockFactory()
 
    @Bean
    ArrivalRepository arrivalRepository() {
        factory.Mock(ArrivalRepository)
    }
}

2. Интеграционный тест

Теперь мы можем использовать фиктивный бин в нашем интеграционном тесте Grails 3, вводя его по типу с помощью @Autowired . Мы можем создать ожидания как обычно.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Integration
class ArrivalApiIntegrationSpec extends Specification {
 
    @Value('${local.server.port}')
    Integer serverPort
 
    @Autowired
    ArrivalRepository mockedArrivalRepository
 
    void "should create an arrival"() {
 
        given:
        1 * mockedArrivalRepository.registerArrival(_) >> {
            Optional.empty()
        }
 
        when:
        def response = new RestBuilder().post('http://localhost:{serverPort}/api/arrivals') {
            urlVariables([serverPort: serverPort])
            json {
                animalId = 1
                date = '2017-01-01'
            }
        }
 
        then:
        response.status == 200
    }
}

3. Зависимость

Для того чтобы вышесказанное сработало, вам действительно необходимо включить одну существенную зависимость от спока-языка .

Добавьте его в свой build.gradle

1
2
3
4
dependencies {
  ...
  testCompile 'org.spockframework:spock-core:1.1-groovy-2.4'
  testCompile 'org.spockframework:spock-spring:1.1-groovy-2.4'

Бада-Бинг. Готово.

это оно

Теперь у нас есть полный контроль над нашими поддельными компонентами, как если бы мы были в модульном тесте.