Это было хорошее время выпуска недавно! Я пишу в блоге Too Much Coding больше о релизах, чем о конкретных темах;)
После выпуска Spring Cloud Sleuth в составе Brixton RC1 мы только что выпустили версию AccuREST 1.0.4. Мы исправили несколько ошибок, но ввели несколько важных функций, в том числе:
- Поддержка плагинов Maven
- Функциональность Stub Runner
Этот пост опишет последнюю функцию более подробно.
Вступление
Я довольно много говорил о библиотеке под названием Micro-Infra-Spring, где я представил, как можно извлечь выгоду из функциональности Stub Runner . С тех пор как я покинул компанию, владеющую этим хранилищем, проект практически не обслуживался. В течение достаточно долгого времени любая разработка была сделана главным образом мной, и фактически я был автором большей части кода Stub Runner . Из-за вышеупомянутого и того факта, что Stub Runner тесно связан с функцией создания заглушек AccuREST, я решил перенести ее в репозиторий AccuREST.
Точное резюме
Stub Runner тесно связан с концепциями AccuREST. Для получения дополнительной информации о AccuREST вы можете проверить мои записи в блоге или проверить проект AccuREST на Github . Если вы не знаете, что это такое, я постараюсь сделать очень быстрое резюме.
AccuREST — это верификатор Consumer Driven Contracts, в котором вы определяете контракт вашего API через Groovy DSL. Из этого DSL на стороне сервера создаются тесты, чтобы проверить, говорит ли ваш контракт правду. С точки зрения Stub Runner более интересной является сторона клиента. Для клиентской стороны AccuREST генерирует заглушки WireMock из предоставленного DSL, чтобы клиентам этого API можно было предоставить надежные заглушки.
Что такое огрызок?
Теперь, когда мы помним, что делает AccuREST, мы можем более подробно взглянуть на Stub Runner . Давайте предположим, что у нас есть следующий поток услуг (кстати, это скриншот Zipkin, интегрированного с Spring Cloud Sleuth )
Давайте представим себя разработчиками сервиса2, который называет сервис3 и сервис4 . Поскольку мы используем подход CDC ( Consumer Driven Contracts ), давайте предположим, что заглушки service3 и service4 уже развернуты в некотором репозитории Maven.
Если я пишу интеграционные тесты service2, у меня наверняка будут некоторые точки взаимодействия с service3 и service4 . Скорее всего, в большинстве случаев я просто высмеиваю эти взаимодействия в своем коде, но было бы полезно сделать реальный HTTP-вызов для другого приложения. Конечно, я не хочу загружать оба сервиса и запускать их только для интеграционных тестов — это было бы излишним. Вот почему наиболее предпочтительным решением на этом этапе будет запускать заглушки моих сотрудников.
Поскольку мне лень что-то делать вручную, я бы предпочел, чтобы заглушки автоматически загружались для меня, серверы WireMock запускались и получали определения заглушек.
И это именно то, что Stub Runner может сделать для вас!
Как это работает?
концепция
По своей сути Stub Runner использует механизм Groovy Grape для загрузки заглушек из заданного репозитория Maven. Затем он распаковывает их во временную папку. Предположим, у вас есть следующая структура ваших заглушек WireMock внутри JAR-заглушки (пример для service3-stubs.jar
)
1
2
3
4
5
6
7
|
├── META-INF │ └── MANIFEST.MF └── mappings └── service3 ├── shouldMarkClientAsFraud.json ├── notAWireMockMapping.json └── shouldSayHello.json |
Stub Runner просканирует весь распакованный JAR- .json
на .json
файлов .json
. Существует соглашение, что определения заглушек помещаются в папку mappings
. Поэтому он выберет shouldMarkClientAsFraud.json
, notAWireMockMapping.json
и shouldSayHello.json
.
Затем для каждой зависимости запускается экземпляр WireMock, и каждый найденный JSON пытается проанализировать как определение заглушки WireMock. Любые исключения в этой точке игнорируются (при условии, что notAWireMockMapping.json
не является допустимым определением WireMock, исключение будет подавлено). В нашем сценарии будут запущены 2 сервера WireMock — один для service3
и один для service4
.
Таким образом, вам не нужно копировать заглушки вручную. Заглушки централизованы, так как они хранятся в репозитории Maven. Это чрезвычайно важно, потому что Stub Runner всегда загружает самую новую версию заглушек, поэтому вы можете быть уверены, что ваши тесты прервутся, как только кто-нибудь внесет несовместимые изменения.
API
С точки зрения разработчика, есть только несколько классов Stub Runner, которые следует использовать. В большинстве случаев вы будете использовать следующие:
StubFinder
Интерфейс, который позволяет вам найти URL запущенного экземпляра WireMock. Вы можете найти этот URL, передав нотацию Ivy ( groupId:artifactId
) или просто artifactId
— Stub Runner попытается позаботиться об остальном.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
interface StubFinder { /** * For the given groupId and artifactId tries to find the matching * URL of the running stub. * * @param groupId - might be null. In that case a search only via artifactId takes place * @return URL of a running stub or null if not found */ URL findStubUrl(String groupId, String artifactId) /** * For the given Ivy notation {@code groupId:artifactId} tries to find the matching * URL of the running stub. You can also pass only {@code artifactId}. * * @param ivyNotation - Ivy representation of the Maven artifact * @return URL of a running stub or null if not found */ URL findStubUrl(String ivyNotation) /** * Returns all running stubs */ RunningStubs findAllRunningStubs() } |
RunningStubs
Структура, представляющая уже запущенные заглушки. Дайте вам несколько вспомогательных методов, чтобы получить представление Ivy для конкретной заглушки, найти порт для заглушки и т. Д.
StubRunning
Контракт для классов, которые могут запускать заглушки:
1
2
3
4
5
6
7
|
interface StubRunning extends Closeable, StubFinder { /** * Runs the stubs and returns the {@link RunningStubs} */ RunningStubs runStubs() } |
StubRunner
Представляет один экземпляр готовых к работе заглушек. Он может запустить заглушки и вернет запущенный экземпляр WireMock, завернутый в класс RunningStubs
. Поскольку он реализует StubFinder
его также можно запросить, если текущий groupid и artifactid соответствуют соответствующей запущенной заглушке.
BatchStubRunner
Если у вас есть несколько служб, для которых вы хотите запустить WireMocks с заглушками, достаточно использовать BatchStubRunner
. Он перебирает данный Iterable
из StubRunner
и выполняет логику для каждого из них.
Бегущий огрызок
Во всех приведенных ниже примерах предположим, что заглушки хранятся в репозитории Maven, доступном по адресу http://toomuchcoding.com
. В качестве service2 я хотел бы загрузить заглушки com.toomuchcoding:service3
и com.toomuchcoding:service4
services.
Заглушка как толстый баночка
Как это использовать?
Stub Runner поставляется с основным классом ( io.codearte.accurest.stubrunner.StubRunnerMain
), который можно запускать со следующими параметрами:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
-maxp (--maxPort) N : Maximum port value to be assigned to the Wiremock instance. Defaults to 15000 ( default : 15000 ) -minp (--minPort) N : Minimal port value to be assigned to the Wiremock instance. Defaults to 10000 ( default : 10000 ) -s (--stubs) VAL : Comma separated list of Ivy representation of jars with stubs. Eg. groupid:artifactid1,group id2:artifactid2:classifier -sr (--stubRepositoryRoot) VAL : Location of a Jar containing server where you keep your stubs (e.g. http: //nexus.net/content /repositories/repository) -ss (--stubsSuffix) VAL : Suffix for the jar containing stubs (e.g. 'stubs' if the stub jar would have a 'stubs' classifier for stubs: foobar-stubs ). Defaults to 'stubs' ( default : stubs) -wo (--workOffline) : Switch to work offline. Defaults to 'false' ( default : false ) |
Вы можете запустить этот основной класс из IDE или создать себе толстый JAR. Для этого достаточно вызвать следующую команду:
1
|
./gradlew stub-runner-root:stub-runner:shadowJar -PfatJar |
Затем внутри build/lib
будет толстый JAR с классификатором fatJar
ожидающим вашего выполнения.
Возвращаясь к нашему примеру после создания толстого JAR- файла, я бы просто вызвал следующую команду, чтобы получить заглушки service3 и service4 из репозитория Maven, доступного по адресу http://toomuchcoding.com
.
1
|
java -jar stub-runner-1.0.4-SNAPSHOT-fatJar.jar -sr http: //toomuchcoding .com -s com.toomuchcoding:service3:stubs,com.toomuchcoding.service4 |
Когда это использовать?
Запуск Stub Runner в качестве основного класса наиболее целесообразен, когда вы запускаете быстрые дымовые тесты для развернутого приложения, где вы не хотите загружать и запускать всех сотрудников этого приложения. Для более разумного обоснования такого подхода вы можете проверить мою статью о развертывании Microservice
Заглушка Бегун Юнит Правило
Как это использовать?
Вы можете использовать правило JUnit для Stub Runner, чтобы автоматически загружать и запускать заглушки во время ваших тестов. AccurestRule
реализует интерфейс StubFinder
поэтому вы можете легко найти URL-адреса интересующих вас сервисов.
Вот как вы могли бы сделать это со Споком:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
class SomeSpec extends Specification { @ClassRule @Shared AccurestRule rule = new AccurestRule() .downloadStub( "com.toomuchcoding" , "service3" ) .downloadStub( "com.toomuchcoding:service4" ) def 'should do something useful when service3 is called' () { given: URL service3Url = rule.findStubUrl( 'com.toomuchcoding' , 'service3' ) expect: somethingUseful(service3Url) } def 'should do something even more useful when service4 is called' () { given: URL service4Url = rule.findStubUrl( 'service4' ) expect: somethingMoreUseful(service4Url) } } |
или с простым Java JUnit:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
public class SomeTest { @ClassRule public static AccurestRule rule = new AccurestRule() .downloadStub( "com.toomuchcoding" , "service3" ) .downloadStub( "com.toomuchcoding:service4" ); @Test public void should_do_something_useful_when_service3_is_called() { URL service3Url = rule.findStubUrl( "com.toomuchcoding" , "service3" ); somethingUseful(service3Url); } @Test public void should_do_something_even_more_useful_when_service4_is_called() { URL service4Url = rule.findStubUrl( "service4" ); somethingMoreUseful(service4Url); } } |
Когда это использовать?
Вы можете использовать это правило в любом месте, где захотите, если мы не обеспечим интеграцию с существующей структурой.
Заглушка бегун весна
Как это использовать?
Вы можете использовать конфигурацию Spring для Stub Runner, чтобы загрузить заглушки ваших соавторов и запустить сервер WireMock при загрузке контекста Spring. Мы предоставляем StubRunnerConfiguration
которую вы можете импортировать в свои тесты. В этой конфигурации мы регистрируем боб StubFinder
который вы можете автоматически подключать в своих тестах.
Имея следующий файл application.yaml
:
1
2
|
stubrunner.stubs.repository.root: http: //toomuchcoding .com stubrunner.stubs.ids: com.toomuchcoding:service3:stubs,com.toomuchcoding.service4 |
Вот как ты мог сделать это со Споком
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
|
@ContextConfiguration (classes = Config, loader = SpringApplicationContextLoader) class StubRunnerConfigurationSpec extends Specification { @Autowired StubFinder stubFinder def 'should do something useful when service3 is called' () { given: URL service3Url = stubFinder.findStubUrl( 'com.toomuchcoding' , 'service3' ) expect: somethingUseful(service3Url) } def 'should do something even more useful when service4 is called' () { given: URL service4Url = stubFinder.findStubUrl( 'service4' ) expect: somethingMoreUseful(service4Url) } @Configuration @Import (StubRunnerConfiguration) @EnableAutoConfiguration static class Config {} } |
Когда это использовать?
В ваших тестах, если у вас есть Spring и у вас нет Spring Cloud. Также вы можете добавить его во время компиляции (разумеется, вам придется добавить несколько профилей Spring, чтобы не запускать его на производстве), чтобы получить прибыль от режима «разработки» запуска микросервисов. Это означает, что если вы загрузите свое приложение, чтобы щелкнуть по нему — все заглушки вокруг вас уже будут загружены и запущены.
Stub Runner Весеннее Облако
Как это использовать?
Вы можете использовать конфигурацию Spring Cloud для Stub Runner, чтобы получать выгоду от заштрихованных соавторов при использовании абстракций Spring Cloud над обнаружением служб и при использовании ленты Netflix. Конфигурация Stub Runner Spring Cloud является AutoConfiguration
поэтому она автоматически запускается для вас.
Предположим, что вы ссылаетесь на service3 как на service3
в своем коде, а на service4 — на shouldMapThisNameToService4
. Это означает, что вы используете, например, @LoadBalanced
RestTemplate
следующим образом (не используйте инъекцию полей, как я делаю в этом примере !!):
01
02
03
04
05
06
07
08
09
10
11
12
13
|
@Component class SomeClass { @Autowired @LoadBalanced RestTemplate restTemplate void doSth() { // code... String service4Response = restTemplate.getForObject( 'http://shouldMapThisNameToService4/name' , String) // more code... } } |
Если идентификатор службы, который вы используете для вызова других служб, отображается точно на имя идентификатора артефакта в репозитории Maven, то вам повезло, и вам не нужно ничего делать, чтобы найти работающие заглушки. Однако если это не так — не волнуйтесь, вам просто нужно сопоставить это самостоятельно.
Свойство stubrunner.stubs.idsToServiceIds
является корневым путем к карте, в которой ключ является идентификатором артефакта загруженной заглушки, а значение — идентификатором службы, используемым в коде.
Имея следующий файл application.yaml
:
1
2
3
4
5
|
stubrunner.stubs.repository.root: http: //toomuchcoding .com stubrunner.stubs.ids: com.toomuchcoding:service3:stubs,com.toomuchcoding.service4 stubrunner.stubs.idsToServiceIds: service4: shouldMapThisNameToService4 |
Вот как ты мог сделать это со Споком
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
@ContextConfiguration (classes = Config, loader = SpringApplicationContextLoader) class StubRunnerConfigurationSpec extends Specification { @Autowired SomeClass someClass def 'should not explode' () { when: someClass.doSth() expect: noExceptionThrown() } @Configuration @EnableAutoConfiguration static class Config {} } |
Когда это использовать?
Когда вы используете Spring Cloud. Вы можете получить прибыль от Stub Runner Spring Cloud
также в режиме «разработчика», как представлено в разделе « Stub Runner Spring
».
Дополнительные параметры конфигурации
Вы можете установить значение по умолчанию для репозитория Maven с помощью системного свойства:
1
|
-Dstubrunner.stubs.repository.root=http: //your.maven.repo.com |
Список настраиваемых свойств содержит:
название | Значение по умолчанию | Описание |
---|---|---|
stubrunner.port.range.min | 10000 | Минимальное значение порта для сервера WireMock |
stubrunner.port.range.max | 15000 | Максимальное значение порта для сервера WireMock |
stubrunner.stubs.repository.root | Адрес вашего репо М2 (будет указывать на локальный репо М2, если ничего не указано) | |
stubrunner.stubs.classifier | заглушки | Классификатор по умолчанию для JAR-файлов, содержащих заглушки |
stubrunner.work-форум | ложный | Следует попробовать подключиться к любому репо, чтобы загрузить заглушки (полезно, если нет интернета) |
stubrunner.stubs | Список заглушек по умолчанию, разделенных запятой |
Резюме
Заглушка Бегун :
- Уже зарекомендовал себя как очень полезный инструмент при выполнении CDC.
- Был испытан в бою, и все больше компаний заявляют о своей заинтересованности в его использовании.
- Помогает вам создать API, который должен сделать обе стороны (сервер и клиент) одинаково счастливыми (или несчастными, но все же они оба равны в своих эмоциях;)).
- Независимо от языка / технологии — вы можете запустить его как полноценный JAR, использовать его с Spring, Guice или с чем угодно.
- Помогает ускорить цикл обратной связи как с точки зрения дизайна API, так и с точки зрения совместимости.
связи
Ссылка: | AccuREST Stub Runner Выпущен от нашего партнера по JCG Марцина Грэйсчака в блоге для кодирования блогов наркоманов . |