├── get-composer.sh
├── src
└── WireMock
│ ├── Serde
│ ├── SerializationException.php
│ ├── ClassDiscriminator.php
│ ├── PropNaming
│ │ ├── PropertyNamingStrategy.php
│ │ ├── ConstantPropertyNamingStrategy.php
│ │ └── ReferencingPropertyNamingStrategy.php
│ ├── Type
│ │ ├── SerdeTypeUntypedArray.php
│ │ ├── SerdeType.php
│ │ ├── SerdeTypeSingle.php
│ │ ├── SerdeTypeNull.php
│ │ ├── SerdeTypeArray.php
│ │ ├── SerdeTypeTypedArray.php
│ │ ├── SerdeTypePrimitive.php
│ │ ├── SerdeTypeLookup.php
│ │ ├── SerdeTypeAssocArray.php
│ │ └── SerdeTypeUnion.php
│ ├── CanonicalNameUtils.php
│ ├── ArrayMapUtils.php
│ ├── SerializerFactory.php
│ ├── MethodFactory.php
│ ├── StaticFactoryMethodValidator.php
│ ├── ClassDiscriminatorMapping.php
│ ├── SerdeClassDiscriminationInfo.php
│ ├── SerdeProp.php
│ ├── SerdeClassDefinition.php
│ └── Serializer.php
│ ├── Stubbing
│ ├── Fault.php
│ ├── StubImport.php
│ ├── StubImportOptions.php
│ ├── ScenarioMapping.php
│ ├── Scenario.php
│ ├── StubImportBuilder.php
│ └── StubMapping.php
│ ├── Http
│ └── RequestMethod.php
│ ├── Client
│ ├── MatchResult.php
│ ├── CountMatchingRequestsResult.php
│ ├── FindNearMissesResult.php
│ ├── FindRequestsResult.php
│ ├── GetScenariosResult.php
│ ├── JsonPathValueMatchingStrategy.php
│ ├── EqualToMatchingStrategy.php
│ ├── ListStubMappingsResult.php
│ ├── RequestJournalDependentResult.php
│ ├── GetServeEventsResult.php
│ ├── VerificationException.php
│ ├── BasicCredentials.php
│ ├── PaginatedResult.php
│ ├── UnmatchedRequests.php
│ ├── DateTimeMatchExpectedOffset.php
│ ├── JsonValueMatchingStrategy.php
│ ├── LogicalOperatorMatchingStrategy.php
│ ├── LoggedResponse.php
│ ├── AdvancedPathPattern.php
│ ├── XPathValueMatchingStrategy.php
│ ├── XmlUnitComparisonType.php
│ ├── MultipartValuePattern.php
│ ├── NearMiss.php
│ ├── ScenarioMappingBuilder.php
│ ├── ClientException.php
│ ├── MultipartValuePatternBuilder.php
│ ├── ServeEvent.php
│ ├── HttpWait.php
│ ├── EqualToXmlMatchingStrategy.php
│ ├── Curl.php
│ ├── LoggedRequest.php
│ ├── ServeEventQuery.php
│ ├── DateTimeMatchingStrategy.php
│ ├── ValueMatchingStrategy.php
│ └── RequestPatternBuilder.php
│ ├── Fault
│ ├── GlobalDelaySettings.php
│ ├── FixedDelay.php
│ ├── UniformDistribution.php
│ ├── LogNormal.php
│ ├── ChunkedDribbleDelay.php
│ └── DelayDistribution.php
│ ├── Recording
│ ├── RecordingStatusResult.php
│ ├── SnapshotRecordResult.php
│ ├── ProxiedServeEventFilters.php
│ └── RecordSpec.php
│ ├── PostServe
│ ├── PostServeAction.php
│ └── WebhookDefinition.php
│ ├── Matching
│ ├── CustomMatcherDefinition.php
│ ├── UrlMatchingStrategy.php
│ └── RequestPattern.php
│ ├── SerdeGen
│ ├── Tag
│ │ ├── SerdeCatchAllTag.php
│ │ ├── SerdeUnwrappedTag.php
│ │ ├── SerdeNamedByTag.php
│ │ ├── SerdeDiscriminateTypeTag.php
│ │ ├── SerdeNameTag.php
│ │ ├── SerdePossibleNamesTag.php
│ │ └── SerdePossibleSubtypeTag.php
│ ├── SerdeTypeLookupFactory.php
│ ├── PartialSerdeTypeLookup.php
│ └── WireMockSerdeGen.php
│ └── Verification
│ └── CountMatchingStrategy.php
├── test
├── WireMock
│ ├── SerdeGen
│ │ ├── TestClasses
│ │ │ ├── KitchenSinkSubA.php
│ │ │ ├── KitchenSinkSubB.php
│ │ │ ├── OneSimpleField.php
│ │ │ ├── CatchAllPrimitiveProperty.php
│ │ │ └── KitchenSink.php
│ │ └── WireMockSerdeGenTest.php
│ ├── Serde
│ │ ├── TestClasses
│ │ │ ├── DefaultedField.php
│ │ │ ├── NamedProperty.php
│ │ │ ├── ClassTypeFields.php
│ │ │ ├── UnwrappedArrayProperty.php
│ │ │ ├── DiscriminatedTypeSubclassA.php
│ │ │ ├── DiscriminatedTypeSubclassB.php
│ │ │ ├── UnwrappedPrimitiveProperty.php
│ │ │ ├── CatchAllAndNamedProperty.php
│ │ │ ├── UnwrappedAndNamedProperty.php
│ │ │ ├── CatchAllAndNamedByProperty.php
│ │ │ ├── UnwrappedAndNamedByProperty.php
│ │ │ ├── UnwrappedClassProperty.php
│ │ │ ├── CatchAllUntypedArrayProperty.php
│ │ │ ├── CatchAllTypedArrayProperty.php
│ │ │ ├── PrimitiveArrayFields.php
│ │ │ ├── CatchAllAssocArrayProperty.php
│ │ │ ├── FieldOnlyPrimitives.php
│ │ │ ├── NamedByProperty.php
│ │ │ ├── ConstructorParams.php
│ │ │ ├── UnionTypeFields.php
│ │ │ └── DiscriminatedTypeParent.php
│ │ ├── Type
│ │ │ ├── SerdeTypeArrayTest.php
│ │ │ ├── SerdeTypeNullTest.php
│ │ │ └── SerdeTypePrimitiveTest.php
│ │ └── SerializerTest.php
│ ├── Integration
│ │ ├── ShutdownIntegrationTest.php
│ │ ├── MappingsAssertionFunctions.php
│ │ ├── WireMockIntegrationTest.php
│ │ ├── ProxyingIntegrationTest.php
│ │ ├── TestClient.php
│ │ ├── NearMissesIntegrationTest.php
│ │ ├── WebhookIntegrationTest.php
│ │ ├── MultipartIntegrationTest.php
│ │ └── MappingsIntegrationTest.php
│ ├── HamcrestTestCase.php
│ ├── Matching
│ │ ├── UrlMatchingStrategyTest.php
│ │ └── RequestPatternTest.php
│ ├── Client
│ │ ├── ValueMatchingStrategyTest.php
│ │ ├── MappingBuilderTest.php
│ │ └── RequestPatternBuilderTest.php
│ └── Stubbing
│ │ └── StubMappingTest.php
├── exec_test.sh
├── phpunit.xml
└── bootstrap.php
├── .gitignore
├── wiremock
├── stop.sh
└── start.sh
├── .circleci
└── config.yml
├── LICENSE-MIT.txt
├── composer.json
└── Readme.md
/get-composer.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | curl -s http://getcomposer.org/installer | php
--------------------------------------------------------------------------------
/src/WireMock/Serde/SerializationException.php:
--------------------------------------------------------------------------------
1 | sleep.log 2>&1 &
--------------------------------------------------------------------------------
/test/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | .
5 |
6 |
7 |
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/NamedProperty.php:
--------------------------------------------------------------------------------
1 | primitiveTypes = $primitiveTypes;
13 | }
14 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/Type/SerdeTypeUntypedArray.php:
--------------------------------------------------------------------------------
1 | unwrappedArray = $unwrappedArray;
16 | }
17 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/Type/SerdeType.php:
--------------------------------------------------------------------------------
1 | subclassAProp = $subclassAProp;
14 | }
15 | }
--------------------------------------------------------------------------------
/test/WireMock/Integration/ShutdownIntegrationTest.php:
--------------------------------------------------------------------------------
1 | shutdownServer();
11 |
12 | // then
13 | assertThat(self::$_wireMock->isShutDown(), is(true));
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/DiscriminatedTypeSubclassB.php:
--------------------------------------------------------------------------------
1 | subclassBProp = $subclassBProp;
14 | }
15 | }
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/UnwrappedPrimitiveProperty.php:
--------------------------------------------------------------------------------
1 | unwrappedPrimitive = $unwrappedPrimitive;
16 | }
17 | }
--------------------------------------------------------------------------------
/test/WireMock/SerdeGen/TestClasses/CatchAllPrimitiveProperty.php:
--------------------------------------------------------------------------------
1 | catchAllPrimitive = $catchAllPrimitive;
16 | }
17 | }
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/CatchAllAndNamedProperty.php:
--------------------------------------------------------------------------------
1 |
9 | * @serde-catch-all
10 | * @serde-name ignoredSerializedName
11 | */
12 | private $original;
13 |
14 | public function __construct(array $original)
15 | {
16 | $this->original = $original;
17 | }
18 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/ArrayMapUtils.php:
--------------------------------------------------------------------------------
1 | original = $original;
17 | }
18 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/SerializerFactory.php:
--------------------------------------------------------------------------------
1 | distance = $distance;
16 | }
17 |
18 | /**
19 | * @return float
20 | */
21 | public function getDistance()
22 | {
23 | return $this->distance;
24 | }
25 | }
--------------------------------------------------------------------------------
/wiremock/stop.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # This is executed from the tests, so the current working directory is the tests folder.
4 | # Change to the wiremock directory
5 | cd ../wiremock
6 |
7 | instance=1
8 | if [ $# -gt 0 ]; then
9 | instance=$1
10 | fi
11 | pidFile=wiremock.$instance.pid
12 |
13 |
14 | if [ -e $pidFile ]; then
15 | kill -9 `cat $pidFile`
16 | rm $pidFile
17 | else
18 | echo WireMock is not started 2>&1
19 | exit 1
20 | fi
21 |
22 | echo WireMock $instance stopped
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/CatchAllAndNamedByProperty.php:
--------------------------------------------------------------------------------
1 |
9 | * @serde-catch-all
10 | * @serde-named-by namer
11 | * @serde-possible-names possibleNames
12 | */
13 | private $prop;
14 | /** @var string */
15 | private $namer;
16 |
17 | private static function possibleNames(): array { return ['newName']; }
18 | }
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/UnwrappedAndNamedByProperty.php:
--------------------------------------------------------------------------------
1 | count = $count;
16 | }
17 |
18 | /**
19 | * @return integer
20 | */
21 | public function getCount()
22 | {
23 | return $this->count;
24 | }
25 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/Type/SerdeTypeSingle.php:
--------------------------------------------------------------------------------
1 | typeString = $typeString;
16 | }
17 |
18 | public function displayName(): string
19 | {
20 | return $this->typeString;
21 | }
22 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/MethodFactory.php:
--------------------------------------------------------------------------------
1 | = 80400
15 | ? ReflectionMethod::createFromMethodName($fqMethodName)
16 | : new ReflectionMethod($fqMethodName);
17 | }
18 | }
--------------------------------------------------------------------------------
/test/WireMock/HamcrestTestCase.php:
--------------------------------------------------------------------------------
1 | addToAssertionCount(MatcherAssert::getCount());
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/UnwrappedClassProperty.php:
--------------------------------------------------------------------------------
1 | topLevel = $topLevel;
18 | $this->unwrappedClass = $unwrappedClass;
19 | }
20 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/FindNearMissesResult.php:
--------------------------------------------------------------------------------
1 | nearMisses = $nearMisses;
16 | }
17 |
18 | /**
19 | * @return NearMiss[]
20 | */
21 | public function getNearMisses()
22 | {
23 | return $this->nearMisses;
24 | }
25 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/FindRequestsResult.php:
--------------------------------------------------------------------------------
1 | requests = $requests;
16 | }
17 |
18 | /**
19 | * @return LoggedRequest[]
20 | */
21 | public function getRequests(): array
22 | {
23 | return $this->requests;
24 | }
25 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/GetScenariosResult.php:
--------------------------------------------------------------------------------
1 | scenarios = $scenarios;
18 | }
19 |
20 | /**
21 | * @return Scenario[]
22 | */
23 | public function getScenarios()
24 | {
25 | return $this->scenarios;
26 | }
27 | }
--------------------------------------------------------------------------------
/src/WireMock/Fault/GlobalDelaySettings.php:
--------------------------------------------------------------------------------
1 | null, 'fixedDelay' => $millis];
10 | }
11 |
12 | public static function random($distribution)
13 | {
14 | return ['delayDistribution' => $distribution, 'fixedDelay' => null];
15 | }
16 |
17 | public static function none()
18 | {
19 | return ['delayDistribution' => null, 'fixedDelay' => null];
20 | }
21 | }
--------------------------------------------------------------------------------
/src/WireMock/Fault/FixedDelay.php:
--------------------------------------------------------------------------------
1 | milliseconds = $milliseconds;
17 | }
18 |
19 | /**
20 | * @return int
21 | */
22 | public function getMilliseconds(): int
23 | {
24 | return $this->milliseconds;
25 | }
26 | }
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/CatchAllUntypedArrayProperty.php:
--------------------------------------------------------------------------------
1 | topLevel = $topLevel;
22 | $this->catchAll = $catchAll;
23 | }
24 | }
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/CatchAllTypedArrayProperty.php:
--------------------------------------------------------------------------------
1 | topLevel = $topLevel;
22 | $this->catchAll = $catchAll;
23 | }
24 | }
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/PrimitiveArrayFields.php:
--------------------------------------------------------------------------------
1 | */
12 | private $intByString;
13 |
14 | public function __construct(array $untypedArray, array $intArray, array $intByString)
15 | {
16 | $this->untypedArray = $untypedArray;
17 | $this->intArray = $intArray;
18 | $this->intByString = $intByString;
19 | }
20 |
21 |
22 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/JsonPathValueMatchingStrategy.php:
--------------------------------------------------------------------------------
1 | caseInsensitive = $caseInsensitive;
14 | }
15 |
16 | /**
17 | * @return bool
18 | */
19 | public function isCaseInsensitive()
20 | {
21 | return $this->caseInsensitive;
22 | }
23 | }
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/CatchAllAssocArrayProperty.php:
--------------------------------------------------------------------------------
1 |
11 | * @serde-catch-all
12 | */
13 | private $catchAll;
14 |
15 | /**
16 | * @param int $topLevel
17 | * @param array $catchAll
18 | */
19 | public function __construct(int $topLevel, array $catchAll)
20 | {
21 | $this->topLevel = $topLevel;
22 | $this->catchAll = $catchAll;
23 | }
24 | }
--------------------------------------------------------------------------------
/src/WireMock/Recording/RecordingStatusResult.php:
--------------------------------------------------------------------------------
1 | status = $status;
20 | }
21 |
22 | /**
23 | * @return string
24 | */
25 | public function getStatus()
26 | {
27 | return $this->status;
28 | }
29 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/PropNaming/ConstantPropertyNamingStrategy.php:
--------------------------------------------------------------------------------
1 | name = $name;
13 | }
14 |
15 | function getSerializedName(array $data): string
16 | {
17 | return $this->name;
18 | }
19 |
20 | /**
21 | * @return string[]
22 | */
23 | function getPossibleSerializedNames(): array
24 | {
25 | return [$this->name];
26 | }
27 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/Type/SerdeTypeNull.php:
--------------------------------------------------------------------------------
1 | canDenormalize($data)) {
22 | throw new SerializationException('Cannot denormalize non-null data to null');
23 | }
24 | return null;
25 | }
26 | }
--------------------------------------------------------------------------------
/test/WireMock/Matching/UrlMatchingStrategyTest.php:
--------------------------------------------------------------------------------
1 | getMatchingType(), is($matchingType));
18 | assertThat($urlMatchingStrategy->getMatchingValue(), is($matchingValue));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/FieldOnlyPrimitives.php:
--------------------------------------------------------------------------------
1 | int = $int;
20 | $result->float = $float;
21 | $result->bool = $bool;
22 | $result->string = $string;
23 | return $result;
24 | }
25 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/ListStubMappingsResult.php:
--------------------------------------------------------------------------------
1 | mappings = $mappings;
20 | }
21 |
22 |
23 | /**
24 | * @return StubMapping[]
25 | */
26 | public function getMappings()
27 | {
28 | return $this->mappings;
29 | }
30 | }
--------------------------------------------------------------------------------
/test/WireMock/SerdeGen/WireMockSerdeGenTest.php:
--------------------------------------------------------------------------------
1 | getMatchingType(), equalTo($matchingType));
18 | assertThat($valueMatchingStrategy->getMatchingValue(), equalTo($matchingValue));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/WireMock/Client/RequestJournalDependentResult.php:
--------------------------------------------------------------------------------
1 | requestJournalDisabled = $requestJournalDisabled;
18 | }
19 |
20 | /**
21 | * @return bool
22 | */
23 | public function isRequestJournalDisabled()
24 | {
25 | return $this->requestJournalDisabled;
26 | }
27 | }
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/NamedByProperty.php:
--------------------------------------------------------------------------------
1 | valueName = $valueName;
25 | $this->value = $value;
26 | }
27 |
28 | private static function names(): array
29 | {
30 | return ['one', 'two', 'three'];
31 | }
32 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/GetServeEventsResult.php:
--------------------------------------------------------------------------------
1 | requests = $requests;
19 | }
20 |
21 | /**
22 | * @return ServeEvent[]
23 | */
24 | public function getRequests()
25 | {
26 | return $this->requests;
27 | }
28 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/VerificationException.php:
--------------------------------------------------------------------------------
1 | name = $name;
15 | $this->parameters = $parameters;
16 | }
17 |
18 | /**
19 | * @return string
20 | */
21 | public function getName(): string
22 | {
23 | return $this->name;
24 | }
25 |
26 | /**
27 | * @return WebhookDefinition
28 | */
29 | public function getParameters(): WebhookDefinition
30 | {
31 | return $this->parameters;
32 | }
33 | }
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/ConstructorParams.php:
--------------------------------------------------------------------------------
1 | fieldWithConstructorParam = $fieldWithConstructorParam;
20 | $this->fieldWithOptionalConstructorParam = $fieldWithOptionalConstructorParam;
21 | }
22 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/BasicCredentials.php:
--------------------------------------------------------------------------------
1 | username = $username;
19 | $this->password = $password;
20 | }
21 |
22 | /**
23 | * @return string
24 | */
25 | public function getUsername()
26 | {
27 | return $this->username;
28 | }
29 |
30 | /**
31 | * @return string
32 | */
33 | public function getPassword()
34 | {
35 | return $this->password;
36 | }
37 | }
--------------------------------------------------------------------------------
/src/WireMock/Matching/CustomMatcherDefinition.php:
--------------------------------------------------------------------------------
1 | name = $name;
19 | $this->parameters = $parameters;
20 | }
21 |
22 | /**
23 | * @return string
24 | */
25 | public function getName()
26 | {
27 | return $this->name;
28 | }
29 |
30 | /**
31 | * @return array
32 | */
33 | public function getParameters()
34 | {
35 | return $this->parameters;
36 | }
37 | }
--------------------------------------------------------------------------------
/src/WireMock/Fault/UniformDistribution.php:
--------------------------------------------------------------------------------
1 | lower = $lower;
20 | $this->upper = $upper;
21 | }
22 |
23 | /**
24 | * @return int
25 | */
26 | public function getLower()
27 | {
28 | return $this->lower;
29 | }
30 |
31 | /**
32 | * @return int
33 | */
34 | public function getUpper()
35 | {
36 | return $this->upper;
37 | }
38 | }
--------------------------------------------------------------------------------
/src/WireMock/Fault/LogNormal.php:
--------------------------------------------------------------------------------
1 | median = $median;
20 | $this->sigma = $sigma;
21 | }
22 |
23 | /**
24 | * @return float
25 | */
26 | public function getMedian()
27 | {
28 | return $this->median;
29 | }
30 |
31 | /**
32 | * @return float
33 | */
34 | public function getSigma()
35 | {
36 | return $this->sigma;
37 | }
38 | }
--------------------------------------------------------------------------------
/src/WireMock/SerdeGen/Tag/SerdeCatchAllTag.php:
--------------------------------------------------------------------------------
1 | format($this);
27 | }
28 |
29 | public function __toString(): string
30 | {
31 | return '';
32 | }
33 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/StaticFactoryMethodValidator.php:
--------------------------------------------------------------------------------
1 | isStatic()) {
16 | throw new SerializationException("$fqMethodName must be a static method but is not");
17 | }
18 | $numRequiredParams = $refMethod->getNumberOfRequiredParameters();
19 | if ($numRequiredParams > 0) {
20 | throw new SerializationException("$fqMethodName must take no required args, but requires $numRequiredParams");
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/src/WireMock/SerdeGen/Tag/SerdeUnwrappedTag.php:
--------------------------------------------------------------------------------
1 | format($this);
27 | }
28 |
29 | public function __toString(): string
30 | {
31 | return '';
32 | }
33 | }
--------------------------------------------------------------------------------
/src/WireMock/Recording/SnapshotRecordResult.php:
--------------------------------------------------------------------------------
1 | mappings = $mappings;
21 | $this->ids = $ids;
22 | }
23 |
24 | /**
25 | * @return StubMapping[]
26 | */
27 | public function getMappings()
28 | {
29 | return $this->mappings;
30 | }
31 |
32 | /**
33 | * @return string[]
34 | */
35 | public function getIds()
36 | {
37 | return $this->ids;
38 | }
39 | }
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | orbs:
4 | php: circleci/php@1.1.0
5 |
6 | jobs:
7 | run_tests_and_store_logs:
8 | parameters:
9 | version:
10 | description: The PHP version to use, passed to the executor as tag
11 | type: string
12 | executor:
13 | name: php/default
14 | tag: "<< parameters.version >>-browsers"
15 | steps:
16 | - checkout
17 | - php/install-packages
18 | - run:
19 | command: composer test
20 | - store_artifacts:
21 | path: wiremock/wiremock.1.log
22 | - store_artifacts:
23 | path: wiremock/wiremock.2.log
24 |
25 | workflows:
26 | test_all_versions:
27 | jobs:
28 | - run_tests_and_store_logs:
29 | matrix:
30 | parameters:
31 | version: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
32 |
--------------------------------------------------------------------------------
/src/WireMock/Client/PaginatedResult.php:
--------------------------------------------------------------------------------
1 | meta = $meta;
16 | }
17 |
18 | /**
19 | * @return Meta
20 | */
21 | public function getMeta()
22 | {
23 | return $this->meta;
24 | }
25 | }
26 |
27 | class Meta
28 | {
29 | /** @var int */
30 | private $total;
31 |
32 | /**
33 | * @param int $total
34 | */
35 | public function __construct(int $total)
36 | {
37 | $this->total = $total;
38 | }
39 |
40 | /**
41 | * @return int
42 | */
43 | public function getTotal()
44 | {
45 | return $this->total;
46 | }
47 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/UnmatchedRequests.php:
--------------------------------------------------------------------------------
1 | requestJournalDisabled = $requestJournalDisabled;
19 | $this->requests = $requests;
20 | }
21 |
22 | /**
23 | * @return LoggedRequest[]
24 | */
25 | public function getRequests()
26 | {
27 | return $this->requests;
28 | }
29 |
30 | /**
31 | * @return boolean
32 | */
33 | public function getRequestJournalDisabled()
34 | {
35 | return $this->requestJournalDisabled;
36 | }
37 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/Type/SerdeTypeArray.php:
--------------------------------------------------------------------------------
1 | canDenormalize($data)) {
25 | throw new SerializationException('Cannot denormalize to ' . $this->displayName() .
26 | ' from data of type ' . gettype($data) . ' at path ' . join('.', $path));
27 | }
28 | return $this->denormalizeFromArray($data, $path);
29 | }
30 | }
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/UnionTypeFields.php:
--------------------------------------------------------------------------------
1 | primitivesUnion = $primitivesUnion;
25 | $this->arrayUnion = $arrayUnion;
26 | $this->classUnion = $classUnion;
27 | $this->arrayOfUnion = $arrayOfUnion;
28 | }
29 |
30 | }
--------------------------------------------------------------------------------
/src/WireMock/Fault/ChunkedDribbleDelay.php:
--------------------------------------------------------------------------------
1 | numberOfChunks = $numberOfChunks;
22 | $this->totalDurationMillis = $totalDurationMillis;
23 | }
24 |
25 | /**
26 | * @return int
27 | */
28 | public function getNumberOfChunks()
29 | {
30 | return $this->numberOfChunks;
31 | }
32 |
33 | /**
34 | * @return int
35 | */
36 | public function getTotalDurationMillis()
37 | {
38 | return $this->totalDurationMillis;
39 | }
40 | }
--------------------------------------------------------------------------------
/src/WireMock/Stubbing/StubImport.php:
--------------------------------------------------------------------------------
1 | mappings = $mappings;
20 | $this->importOptions = $importOptions;
21 | }
22 |
23 | /**
24 | * @return StubMapping[]|null
25 | */
26 | public function getMappings(): ?array
27 | {
28 | return $this->mappings;
29 | }
30 |
31 | /**
32 | * @return StubImportOptions
33 | */
34 | public function getImportOptions(): StubImportOptions
35 | {
36 | return $this->importOptions;
37 | }
38 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/DateTimeMatchExpectedOffset.php:
--------------------------------------------------------------------------------
1 | amount = $amount;
25 | $this->unit = $unit;
26 | }
27 |
28 | /**
29 | * @return int
30 | */
31 | public function getAmount(): int
32 | {
33 | return $this->amount;
34 | }
35 |
36 | /**
37 | * @return string
38 | */
39 | public function getUnit(): string
40 | {
41 | return $this->unit;
42 | }
43 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/JsonValueMatchingStrategy.php:
--------------------------------------------------------------------------------
1 | ignoreArrayOrder = $ignoreArrayOrder;
16 | $this->ignoreExtraElements = $ignoreExtraElements;
17 | }
18 |
19 | /**
20 | * @return bool|null
21 | */
22 | public function getIgnoreArrayOrder()
23 | {
24 | return $this->ignoreArrayOrder;
25 | }
26 |
27 | /**
28 | * @return bool|null
29 | */
30 | public function getIgnoreExtraElements()
31 | {
32 | return $this->ignoreExtraElements;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/WireMock/Client/LogicalOperatorMatchingStrategy.php:
--------------------------------------------------------------------------------
1 | expectExceptionMessage('Cannot denormalize');
14 | $serdeType = new class extends SerdeTypeArray {
15 | function displayName(): string { return 'dummy'; }
16 | function denormalizeFromArray(array &$data, array $path): array { return ['dummy array']; }
17 | };
18 | $serdeType->denormalize($data, []);
19 | }
20 |
21 | public function providerNonArrayData(): array
22 | {
23 | return [
24 | 'int' => [123],
25 | 'bool' => [true],
26 | 'float' => [1.23],
27 | 'string' => ['a string'],
28 | 'object' => [$this],
29 | 'null' => [null],
30 | ];
31 | }
32 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/LoggedResponse.php:
--------------------------------------------------------------------------------
1 | status = $status;
22 | $this->headers = $headers;
23 | $this->body = $body;
24 | }
25 |
26 | /**
27 | * @return int
28 | */
29 | public function getStatus()
30 | {
31 | return $this->status;
32 | }
33 |
34 | /**
35 | * @return array
36 | */
37 | public function getHeaders()
38 | {
39 | return $this->headers;
40 | }
41 |
42 | /**
43 | * @return string
44 | */
45 | public function getBody()
46 | {
47 | return $this->body;
48 | }
49 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/AdvancedPathPattern.php:
--------------------------------------------------------------------------------
1 | subMatchingStrategy = $subMatchingStrategy;
22 | $this->expression = $expression;
23 | }
24 |
25 | /**
26 | * @return ValueMatchingStrategy
27 | */
28 | public function getSubMatchingStrategy(): ValueMatchingStrategy
29 | {
30 | return $this->subMatchingStrategy;
31 | }
32 |
33 | /**
34 | * @return string
35 | */
36 | public function getExpression(): string
37 | {
38 | return $this->expression;
39 | }
40 | }
--------------------------------------------------------------------------------
/src/WireMock/Stubbing/StubImportOptions.php:
--------------------------------------------------------------------------------
1 | duplicatePolicy = $duplicatePolicy;
23 | $this->deleteAllNotInImport = $deleteAllNotInImport;
24 | }
25 |
26 | /**
27 | * @return string
28 | */
29 | public function getDuplicatePolicy(): string
30 | {
31 | return $this->duplicatePolicy;
32 | }
33 |
34 | /**
35 | * @return bool
36 | */
37 | public function isDeleteAllNotInImport(): bool
38 | {
39 | return $this->deleteAllNotInImport;
40 | }
41 | }
--------------------------------------------------------------------------------
/src/WireMock/SerdeGen/SerdeTypeLookupFactory.php:
--------------------------------------------------------------------------------
1 | addRootTypes(...$canonicalTypes);
22 | $serdeTypeParser = new SerdeTypeParser($partialLookup);
23 | foreach ($canonicalTypes as $type) {
24 | // This creates the SerdeType and adds it to the lookup as a side-effect
25 | $serdeTypeParser->parseTypeString($type);
26 | }
27 | return $partialLookup;
28 | }
29 | }
--------------------------------------------------------------------------------
/test/WireMock/Integration/MappingsAssertionFunctions.php:
--------------------------------------------------------------------------------
1 | deserialize($adminJson, ListStubMappingsResult::class);
30 | return $listResult->getMappings();
31 | }
32 |
--------------------------------------------------------------------------------
/test/WireMock/Serde/Type/SerdeTypeNullTest.php:
--------------------------------------------------------------------------------
1 | denormalize($data, []);
15 |
16 | assertThat($denormalized, is(null));
17 | }
18 |
19 | /** @dataProvider providerNonNullData */
20 | public function testDenormalizingNonNullThrows($data)
21 | {
22 | $this->expectExceptionMessage('Cannot denormalize');
23 | $serdeType = new SerdeTypeNull();
24 | $serdeType->denormalize($data, []);
25 | }
26 |
27 | public function providerNonNullData(): array
28 | {
29 | return [
30 | 'int' => [123],
31 | 'bool' => [true],
32 | 'float' => [1.23],
33 | 'string' => ['a string'],
34 | 'array' => [[]],
35 | 'object' => [$this]
36 | ];
37 | }
38 | }
--------------------------------------------------------------------------------
/test/WireMock/Serde/TestClasses/DiscriminatedTypeParent.php:
--------------------------------------------------------------------------------
1 | type = $type;
21 | }
22 |
23 | private static function getDiscriminatorMapping()
24 | {
25 | return new ClassDiscriminatorMapping('type', [
26 | 'parent' => DiscriminatedTypeParent::class,
27 | 'a' => DiscriminatedTypeSubclassA::class,
28 | 'b' => DiscriminatedTypeSubclassB::class,
29 |
30 | // Will result in exception at deserialization time, because this is not a registered possible subtype
31 | 'unknown' => FieldOnlyPrimitives::class,
32 | ]);
33 | }
34 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/XPathValueMatchingStrategy.php:
--------------------------------------------------------------------------------
1 | xPathNamespaces[$name] = $namespaceUri;
32 | return $this;
33 | }
34 |
35 | /**
36 | * @return array|null
37 | */
38 | public function getXPathNamespaces(): ?array
39 | {
40 | return $this->xPathNamespaces;
41 | }
42 | }
--------------------------------------------------------------------------------
/src/WireMock/Recording/ProxiedServeEventFilters.php:
--------------------------------------------------------------------------------
1 | requestPattern = $requestPattern;
27 | $this->requestIds = $requestIds;
28 | $this->allowNonProxied = $allowNonProxied;
29 | }
30 |
31 | public function getRequestPattern(): ?RequestPattern
32 | {
33 | return $this->requestPattern;
34 | }
35 |
36 | public function getRequestIds(): ?array
37 | {
38 | return $this->requestIds;
39 | }
40 |
41 | public function getAllowNonProxied(): ?bool
42 | {
43 | return $this->allowNonProxied;
44 | }
45 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/Type/SerdeTypeTypedArray.php:
--------------------------------------------------------------------------------
1 | type = $type;
18 | }
19 |
20 | static function setInnerType(SerdeTypeTypedArray $serdeType, SerdeType $type)
21 | {
22 | $serdeType->type = $type;
23 | }
24 |
25 | public function displayName(): string
26 | {
27 | return $this->type->displayName() . '[]';
28 | }
29 |
30 | /**
31 | * @throws SerializationException
32 | */
33 | function denormalizeFromArray(array &$data, array $path): array
34 | {
35 | $result = [];
36 | foreach ($data as $index => $element) {
37 | $newPath = $path;
38 | $newPath[] = "[$index]";
39 | $result[$index] = $this->type->denormalize($element, $newPath);
40 | }
41 | return $result;
42 | }
43 | }
--------------------------------------------------------------------------------
/LICENSE-MIT.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Rowan Hill
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/WireMock/Fault/DelayDistribution.php:
--------------------------------------------------------------------------------
1 | type = $type;
25 | }
26 |
27 | /**
28 | * @return string
29 | */
30 | public function getType(): string
31 | {
32 | return $this->type;
33 | }
34 |
35 | /** @noinspection PhpUnusedPrivateMethodInspection */
36 | private static function getDiscriminatorMapping(): ClassDiscriminator
37 | {
38 | return new ClassDiscriminatorMapping('type', [
39 | 'lognormal' => LogNormal::class,
40 | 'uniform' => UniformDistribution::class,
41 | 'fixed' => FixedDelay::class
42 | ]);
43 | }
44 | }
--------------------------------------------------------------------------------
/src/WireMock/Matching/UrlMatchingStrategy.php:
--------------------------------------------------------------------------------
1 | matchingType = $matchingType;
29 | $this->matchingValue = $matchingValue;
30 | }
31 |
32 | /**
33 | * @return string
34 | */
35 | public function getMatchingType()
36 | {
37 | return $this->matchingType;
38 | }
39 |
40 | /**
41 | * @return string
42 | */
43 | public function getMatchingValue()
44 | {
45 | return $this->matchingValue;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/test/WireMock/SerdeGen/TestClasses/KitchenSink.php:
--------------------------------------------------------------------------------
1 | reqArg = $reqArg;
54 | }
55 | }
--------------------------------------------------------------------------------
/wiremock/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # This is executed from the tests, so the current working directory is the tests folder.
4 | # Change to the wiremock directory
5 | cd ../wiremock
6 |
7 | instance=1
8 | port=8080
9 | if [ $# -gt 0 ]; then
10 | instance=$1
11 | port=$2
12 | fi
13 | pidFile=wiremock.$instance.pid
14 | logFile=wiremock.$instance.log
15 |
16 | # Ensure WireMock isn't already running
17 | if [ -e $pidFile ]; then
18 | echo WireMock is already started: see process `cat $pidFile` 1>&2
19 | exit 1
20 | fi
21 |
22 | # Download the wiremock jar if we need it
23 | if ! [ -e wiremock-standalone.jar ]; then
24 | echo WireMock standalone JAR missing. Downloading.
25 | curl https://repo1.maven.org/maven2/com/github/tomakehurst/wiremock-jre8-standalone/2.35.0/wiremock-jre8-standalone-2.35.0.jar -o wiremock-standalone.jar
26 | status=$?
27 | if [ ${status} -ne 0 ]; then
28 | echo curl could not download WireMock JAR 1>&2
29 | exit ${status}
30 | fi
31 | fi
32 |
33 | # Start WireMock in standalone mode (in a background process) and save its output to a log
34 | java -jar wiremock-standalone.jar --port $port --root-dir $instance --verbose &> $logFile 2>&1 &
35 | echo $! > $pidFile
36 |
37 | echo WireMock $instance started on port $port
--------------------------------------------------------------------------------
/src/WireMock/Serde/Type/SerdeTypePrimitive.php:
--------------------------------------------------------------------------------
1 | typeString) {
14 | case 'bool':
15 | case 'boolean':
16 | return $dataType === 'boolean';
17 |
18 | case 'int':
19 | case 'integer':
20 | return $dataType === 'integer';
21 |
22 | case 'float':
23 | case 'double':
24 | return $dataType === 'double';
25 |
26 | case 'string':
27 | return $dataType === 'string';
28 |
29 | default:
30 | return false;
31 | }
32 | }
33 |
34 | function denormalize(&$data, array $path)
35 | {
36 | if (!$this->canDenormalize($data)) {
37 | $dataType = gettype($data);
38 | $targetType = $this->displayName();
39 | $joinedPath = join('.', $path);
40 | throw new SerializationException("Cannot deserialize data of type $dataType to $targetType ($joinedPath)");
41 | }
42 | return $data;
43 | }
44 | }
--------------------------------------------------------------------------------
/src/WireMock/SerdeGen/Tag/SerdeNamedByTag.php:
--------------------------------------------------------------------------------
1 | namingPropertyName = $namingPropertyName;
19 | }
20 |
21 | public static function create(string $body)
22 | {
23 | $propName = trim($body);
24 | return new static($propName);
25 | }
26 |
27 | public function getName(): string
28 | {
29 | return 'serde-named-by';
30 | }
31 |
32 | public function getNamingPropertyName(): string
33 | {
34 | return $this->namingPropertyName;
35 | }
36 |
37 | public function render(?Formatter $formatter = null): string
38 | {
39 | if ($formatter === null) {
40 | $formatter = new Formatter\PassthroughFormatter();
41 | }
42 |
43 | return $formatter->format($this);
44 | }
45 |
46 | public function __toString(): string
47 | {
48 | return $this->getNamingPropertyName();
49 | }
50 | }
--------------------------------------------------------------------------------
/src/WireMock/SerdeGen/Tag/SerdeDiscriminateTypeTag.php:
--------------------------------------------------------------------------------
1 | discriminatorFactory = $discriminatorFactory;
19 | }
20 |
21 | public static function create(string $body)
22 | {
23 | return new static(trim($body));
24 | }
25 |
26 | public function getName(): string
27 | {
28 | return 'serde-discriminate-type';
29 | }
30 |
31 | public function getDiscriminatorFactory(): string
32 | {
33 | return $this->discriminatorFactory;
34 | }
35 |
36 | public function render(?Formatter $formatter = null): string
37 | {
38 | if ($formatter === null) {
39 | $formatter = new Formatter\PassthroughFormatter();
40 | }
41 |
42 | return $formatter->format($this);
43 | }
44 |
45 | public function __toString(): string
46 | {
47 | return $this->getDiscriminatorFactory();
48 | }
49 | }
--------------------------------------------------------------------------------
/src/WireMock/Stubbing/ScenarioMapping.php:
--------------------------------------------------------------------------------
1 | scenarioName = $scenarioName;
26 | $this->requiredScenarioState = $requiredScenarioState;
27 | $this->newScenarioState = $newScenarioState;
28 | }
29 |
30 | /**
31 | * @return string
32 | */
33 | public function getScenarioName()
34 | {
35 | return $this->scenarioName;
36 | }
37 |
38 | /**
39 | * @return string
40 | */
41 | public function getRequiredScenarioState()
42 | {
43 | return $this->requiredScenarioState;
44 | }
45 |
46 | /**
47 | * @return string
48 | */
49 | public function getNewScenarioState()
50 | {
51 | return $this->newScenarioState;
52 | }
53 | }
--------------------------------------------------------------------------------
/src/WireMock/SerdeGen/Tag/SerdeNameTag.php:
--------------------------------------------------------------------------------
1 | serializedPropertyName = $serializedPropertyName;
19 | }
20 |
21 | public static function create(string $body)
22 | {
23 | $propName = trim($body);
24 | return new static($propName);
25 | }
26 |
27 | public function getName(): string
28 | {
29 | return 'serde-name';
30 | }
31 |
32 | public function getSerializedPropertyName(): string
33 | {
34 | return $this->serializedPropertyName;
35 | }
36 |
37 | public function render(?Formatter $formatter = null): string
38 | {
39 | if ($formatter === null) {
40 | $formatter = new Formatter\PassthroughFormatter();
41 | }
42 |
43 | return $formatter->format($this);
44 | }
45 |
46 | public function __toString(): string
47 | {
48 | return $this->getSerializedPropertyName();
49 | }
50 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/ClassDiscriminatorMapping.php:
--------------------------------------------------------------------------------
1 | discriminatorPropName = $discriminatorPropName;
19 | $this->discriminatorValueToClassMap = $discriminatorValueToClassMap;
20 | }
21 |
22 | function getDiscriminatedType($data): string
23 | {
24 | $discriminatorName = $this->discriminatorPropName;
25 | if (array_key_exists($discriminatorName, $data)) {
26 | $discriminatorValue = $data[$discriminatorName];
27 | $map = $this->discriminatorValueToClassMap;
28 | if (array_key_exists($discriminatorValue, $map)) {
29 | return $map[$discriminatorValue];
30 | }
31 | }
32 | throw new SerializationException("Could not discriminate class type because $discriminatorName not present in data");
33 | }
34 | }
--------------------------------------------------------------------------------
/src/WireMock/SerdeGen/Tag/SerdePossibleNamesTag.php:
--------------------------------------------------------------------------------
1 | possibleNamesGenerator = $possibleNamesGenerator;
19 | }
20 |
21 | public static function create(string $body)
22 | {
23 | $propName = trim($body);
24 | return new static($propName);
25 | }
26 |
27 | public function getName(): string
28 | {
29 | return 'serde-possible-names';
30 | }
31 |
32 | public function getPossibleNamesGenerator(): string
33 | {
34 | return $this->possibleNamesGenerator;
35 | }
36 |
37 | public function render(?Formatter $formatter = null): string
38 | {
39 | if ($formatter === null) {
40 | $formatter = new Formatter\PassthroughFormatter();
41 | }
42 |
43 | return $formatter->format($this);
44 | }
45 |
46 | public function __toString(): string
47 | {
48 | return $this->getPossibleNamesGenerator();
49 | }
50 | }
--------------------------------------------------------------------------------
/src/WireMock/Stubbing/Scenario.php:
--------------------------------------------------------------------------------
1 | id = $id;
27 | $this->name = $name;
28 | $this->state = $state;
29 | $this->possibleStates = $possibleStates;
30 | }
31 |
32 | /**
33 | * @return string
34 | */
35 | public function getId()
36 | {
37 | return $this->id;
38 | }
39 |
40 | /**
41 | * @return string
42 | */
43 | public function getName()
44 | {
45 | return $this->name;
46 | }
47 |
48 | /**
49 | * @return string
50 | */
51 | public function getState()
52 | {
53 | return $this->state;
54 | }
55 |
56 | /**
57 | * @return string[]
58 | */
59 | public function getPossibleStates()
60 | {
61 | return $this->possibleStates;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/WireMock/Client/XmlUnitComparisonType.php:
--------------------------------------------------------------------------------
1 | =7.2"
33 | },
34 | "require-dev": {
35 | "phpunit/phpunit": "^8.5",
36 | "phake/phake": "^4.5",
37 | "hamcrest/hamcrest-php": "^2.0",
38 | "phpdocumentor/reflection-docblock": "^5.3",
39 | "phpdocumentor/type-resolver": "^1.6"
40 | },
41 |
42 | "suggest": {
43 | "phpunit/phpunit": "Thrown VerificationExceptions automatically fail tests"
44 | },
45 |
46 | "scripts": {
47 | "serdegen": "WireMock\\SerdeGen\\WireMockSerdeGen::generateAndSaveWireMockSerdeLookup",
48 | "test": "cd test && phpunit --configuration phpunit.xml --debug --verbose && cd .."
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/WireMock/SerdeGen/Tag/SerdePossibleSubtypeTag.php:
--------------------------------------------------------------------------------
1 | name = 'serde-possible-subtype';
17 | $this->type = $type;
18 | $this->description = $description;
19 | }
20 |
21 | public static function create(string $body, ?TypeResolver $typeResolver = null, ?TypeContext $context = null)
22 | {
23 | Assert::notNull($typeResolver);
24 | [$typeName, $body] = self::extractTypeFromBody($body);
25 | $type = $typeResolver->resolve($typeName, $context);
26 | $description = new Description($body);
27 |
28 | return new static($type, $description);
29 | }
30 |
31 | public function __toString(): string
32 | {
33 | $type = (string) $this->type;
34 | if ($this->description) {
35 | $description = ' ' . $this->description->render();
36 | } else {
37 | $description = '';
38 | }
39 | return "$type$description";
40 | }
41 | }
--------------------------------------------------------------------------------
/test/WireMock/Integration/WireMockIntegrationTest.php:
--------------------------------------------------------------------------------
1 | isAlive(), is(true));
21 | }
22 |
23 | public static function tearDownAfterClass(): void
24 | {
25 | self::runCmd('./../wiremock/stop.sh');
26 | }
27 |
28 | protected static function runCmd($cmd)
29 | {
30 | $result = 0;
31 | $output = array();
32 | $redirect = EXEC_BLOCKS_ON_OUTPUT ? '> /dev/null' : '';
33 | exec("($cmd) $redirect 2>&1 &", $output, $result);
34 | $output = array_map(function ($line) {
35 | return "\n$line";
36 | }, $output);
37 | echo implode("\n", $output);
38 | assertThat($result, is(0));
39 | }
40 |
41 | public function setUp(): void
42 | {
43 | $this->_testClient = new TestClient();
44 | self::$_wireMock->reset();
45 | }
46 |
47 | public function clearMappings()
48 | {
49 | exec('rm -f ../wiremock/1/mappings/*');
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/test/bootstrap.php:
--------------------------------------------------------------------------------
1 | add("WireMock\\", __DIR__, true);
9 | $classLoader->register();
10 |
11 | \Hamcrest\Util::registerGlobalFunctions();
12 | \Phake::setClient(Phake::CLIENT_PHPUNIT8);
13 |
14 | // Some systems (e.g. OSX) don't block on commands exec()ed in the below fashion. Other systems (e.g. Travis) do.
15 | // Systems which do block need to have their output redirected from stdout/stderr if the command being exec()ed is
16 | // long running.
17 | // Also, some systems (e.g. OSX) fail the tests if the output of starting WireMock is redirected (possibly because
18 | // they're running tests in parallel?), whereas others (e.g. Travis).
19 | // So far, there's a 1-to-1 mapping between these kinds of systems, but it's unclear if that's just chance or not.
20 | // For now, just check which kind of system we're on, so we know whether to redirect output or not.
21 | $startTime = microtime(true);
22 | exec('(./exec_test.sh) 2>&1 &');
23 | $endTime = microtime(true);
24 | $sleepTime = (($endTime - $startTime) * 1000);
25 | echo "Took $sleepTime millis to sleep in background exec()\n";
26 | define('EXEC_BLOCKS_ON_OUTPUT', $sleepTime > 5000);
27 |
28 | // Report all errors - being as strict as possible ensures the library will be compatible with the most environments
29 | error_reporting(E_ALL);
30 |
--------------------------------------------------------------------------------
/src/WireMock/SerdeGen/PartialSerdeTypeLookup.php:
--------------------------------------------------------------------------------
1 | rootTypes[$key] = true;
23 | }
24 | }
25 |
26 | /**
27 | * @throws SerializationException
28 | */
29 | public function addSerdeTypeIfNeeded(string $type, SerdeType $serdeType, bool $isRootType): SerdeType
30 | {
31 | if ($isRootType) {
32 | $this->addRootTypes($type);
33 | }
34 | if (!$this->contains($type)) {
35 | $this->addSerdeType($type, $serdeType);
36 | }
37 | return $this->getSerdeType($type);
38 | }
39 |
40 | private function addSerdeType(string $type, SerdeType $serdeType)
41 | {
42 | $key = CanonicalNameUtils::stripLeadingBackslashIfNeeded($type);
43 | $this->lookup[$key] = $serdeType;
44 | }
45 |
46 | public function contains(string $type): bool
47 | {
48 | $key = CanonicalNameUtils::stripLeadingBackslashIfNeeded($type);
49 | return isset($this->lookup[$key]);
50 | }
51 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/MultipartValuePattern.php:
--------------------------------------------------------------------------------
1 | |null */
13 | private $headers;
14 | /** @var string */
15 | private $name;
16 | /** @var string */
17 | private $matchingType;
18 |
19 | /**
20 | * @param ValueMatchingStrategy[]|null $bodyPatterns
21 | * @param array|null $headers
22 | * @param string $name
23 | * @param string $matchingType
24 | */
25 | public function __construct($bodyPatterns = null, $headers = null, $name = null, $matchingType = null)
26 | {
27 | $this->bodyPatterns = $bodyPatterns;
28 | $this->headers = $headers;
29 | $this->name = $name;
30 | $this->matchingType = $matchingType;
31 | }
32 |
33 | /**
34 | * @return array
35 | */
36 | public function getBodyPatterns()
37 | {
38 | return $this->bodyPatterns;
39 | }
40 |
41 | /**
42 | * @return array
43 | */
44 | public function getHeaders()
45 | {
46 | return $this->headers;
47 | }
48 |
49 | /**
50 | * @return string
51 | */
52 | public function getName()
53 | {
54 | return $this->name;
55 | }
56 |
57 | /**
58 | * @return string
59 | */
60 | public function getMatchingType()
61 | {
62 | return $this->matchingType;
63 | }
64 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/Type/SerdeTypeLookup.php:
--------------------------------------------------------------------------------
1 | */
11 | protected $lookup;
12 | /** @var array */
13 | protected $rootTypes;
14 |
15 | /**
16 | * @param array $lookup
17 | * @param array $rootTypes
18 | */
19 | public function __construct(array $lookup, array $rootTypes)
20 | {
21 | $this->lookup = $lookup;
22 | $this->rootTypes = $rootTypes;
23 | }
24 |
25 | /**
26 | * @throws SerializationException
27 | */
28 | public function getSerdeType(string $type): SerdeType
29 | {
30 | $key = CanonicalNameUtils::stripLeadingBackslashIfNeeded($type);
31 | if (!array_key_exists($key, $this->lookup)) {
32 | throw new SerializationException("Type $key does not exist in the serde type cache");
33 | }
34 | return $this->lookup[$key];
35 | }
36 |
37 | public function getSerdeTypeIfExits(string $type): ?SerdeType
38 | {
39 | $key = CanonicalNameUtils::stripLeadingBackslashIfNeeded($type);
40 | return array_key_exists($key, $this->lookup) ?
41 | $this->lookup[$key] :
42 | null;
43 | }
44 |
45 | public function isRootType(string $type): bool
46 | {
47 | $key = CanonicalNameUtils::stripLeadingBackslashIfNeeded($type);
48 | return array_key_exists($key, $this->rootTypes);
49 | }
50 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/NearMiss.php:
--------------------------------------------------------------------------------
1 | request = $request;
32 | $this->stubMapping = $stubMapping;
33 | $this->requestPattern = $requestPattern;
34 | $this->matchResult = $matchResult;
35 | }
36 |
37 | /**
38 | * @return LoggedRequest
39 | */
40 | public function getRequest()
41 | {
42 | return $this->request;
43 | }
44 |
45 | /**
46 | * @return StubMapping
47 | */
48 | public function getMapping()
49 | {
50 | return $this->stubMapping;
51 | }
52 |
53 | /**
54 | * @return RequestPattern
55 | */
56 | public function getRequestPattern()
57 | {
58 | return $this->requestPattern;
59 | }
60 |
61 | /**
62 | * @return MatchResult
63 | */
64 | public function getMatchResult()
65 | {
66 | return $this->matchResult;
67 | }
68 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/ScenarioMappingBuilder.php:
--------------------------------------------------------------------------------
1 | scenarioName = $scenarioName;
23 | return $this;
24 | }
25 |
26 | /**
27 | * @param string $requiredScenarioState
28 | * @return ScenarioMappingBuilder
29 | */
30 | public function withRequiredState($requiredScenarioState)
31 | {
32 | $this->requiredScenarioState = $requiredScenarioState;
33 | return $this;
34 | }
35 |
36 | /**
37 | * @param string $newScenarioState
38 | * @return ScenarioMappingBuilder
39 | */
40 | public function withNewScenarioState($newScenarioState)
41 | {
42 | $this->newScenarioState = $newScenarioState;
43 | return $this;
44 | }
45 |
46 | /**
47 | * @return null|ScenarioMapping
48 | * @throws \Exception
49 | */
50 | public function build()
51 | {
52 | if ($this->scenarioName === null) {
53 | if ($this->requiredScenarioState !== null || $this->newScenarioState !== null) {
54 | throw new \Exception('Scenario name must be set');
55 | }
56 |
57 | return null;
58 | }
59 |
60 | return new ScenarioMapping($this->scenarioName, $this->requiredScenarioState, $this->newScenarioState);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/WireMock/Serde/Type/SerdeTypeAssocArray.php:
--------------------------------------------------------------------------------
1 | keyType = $keyType;
21 | $this->valueType = $valueType;
22 | }
23 |
24 | static function setKeyValueTypes(
25 | SerdeTypeAssocArray $arrayType,
26 | SerdeTypePrimitive $keySerdeType,
27 | SerdeType $valueSerdeType
28 | ) {
29 | $arrayType->keyType = $keySerdeType;
30 | $arrayType->valueType = $valueSerdeType;
31 | }
32 |
33 | function displayName(): string
34 | {
35 | $key = $this->keyType->displayName();
36 | $value = $this->valueType->displayName();
37 | return "array<$key, $value>";
38 | }
39 |
40 | function denormalizeFromArray(array &$data, array $path): array
41 | {
42 | return ArrayMapUtils::array_map_assoc(
43 | function($key, $value) use ($path) {
44 | $newKeyPath = $path;
45 | $newKeyPath[] = "key<$key>";
46 | $newKey = $this->keyType->denormalize($key, $newKeyPath);
47 |
48 | $newValuePath = $path;
49 | $newValuePath[] = "[$key]";
50 | $newValue = $this->valueType->denormalize($value, $newValuePath);
51 |
52 | return [$newKey, $newValue];
53 | },
54 | $data
55 | );
56 | }
57 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/SerdeClassDiscriminationInfo.php:
--------------------------------------------------------------------------------
1 |
18 | */
19 | private $possibleSerdeTypes;
20 |
21 | /**
22 | * @param string $discriminatorFactoryName
23 | * @param array $possibleSerdeTypes
24 | * @throws SerializationException|ReflectionException
25 | */
26 | public function __construct(string $discriminatorFactoryName, array $possibleSerdeTypes)
27 | {
28 | $this->discriminatorFactoryName = $discriminatorFactoryName;
29 | StaticFactoryMethodValidator::validate($discriminatorFactoryName);
30 | $this->possibleSerdeTypes = $possibleSerdeTypes;
31 | }
32 |
33 | /**
34 | * @throws ReflectionException
35 | */
36 | public function getDiscriminator(): ?ClassDiscriminator
37 | {
38 | $refMethod = MethodFactory::createMethod($this->discriminatorFactoryName);
39 | $refMethod->setAccessible(true);
40 | return $refMethod->invoke(null);
41 | }
42 |
43 | /**
44 | * @throws SerializationException
45 | */
46 | public function getTypeByFullyQualifiedClassName(string $fqn): SerdeTypeClass
47 | {
48 | if (!array_key_exists($fqn, $this->possibleSerdeTypes)) {
49 | throw new SerializationException("Unregistered discriminated subtype $fqn");
50 | }
51 | return $this->possibleSerdeTypes[$fqn];
52 | }
53 | }
--------------------------------------------------------------------------------
/src/WireMock/Verification/CountMatchingStrategy.php:
--------------------------------------------------------------------------------
1 | closure = $closure;
20 | $this->operator = $operator;
21 | $this->operand = $operand;
22 | }
23 |
24 | /**
25 | * @param int $count
26 | * @return boolean
27 | */
28 | public function matches($count)
29 | {
30 | $closure = $this->closure;
31 | return $closure($count);
32 | }
33 |
34 | public function describe()
35 | {
36 | return $this->operator . ' ' . $this->operand;
37 | }
38 |
39 | public static function lessThan($expected) {
40 | return new self(function($actual) use ($expected) { return $actual < $expected; }, '<', $expected);
41 | }
42 |
43 | public static function lessThanOrExactly($expected) {
44 | return new self(function($actual) use ($expected) { return $actual <= $expected; }, '<=', $expected);
45 | }
46 |
47 | public static function exactly($expected) {
48 | return new self(function($actual) use ($expected) { return $actual == $expected; }, '==', $expected);
49 | }
50 |
51 | public static function moreThanOrExactly($expected) {
52 | return new self(function($actual) use ($expected) { return $actual >= $expected; }, '>=', $expected);
53 | }
54 |
55 | public static function moreThan($expected) {
56 | return new self(function($actual) use ($expected) { return $actual > $expected; }, '>', $expected);
57 | }
58 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/ClientException.php:
--------------------------------------------------------------------------------
1 | ", $nestedMessagePieces);
30 | }
31 | }
32 | if (!empty($nestedMessages)) {
33 | $message .= ". Errors were:\n";
34 | $message .= join("\n", $nestedMessages);
35 | }
36 | parent::__construct($message);
37 | $this->_responseCode = $responseCode;
38 | $this->_response = $response;
39 | }
40 |
41 | /**
42 | * @return int
43 | */
44 | public function getResponseCode(): int
45 | {
46 | return $this->_responseCode;
47 | }
48 |
49 | /**
50 | * @return string
51 | */
52 | public function getResponse(): string
53 | {
54 | return $this->_response;
55 | }
56 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/MultipartValuePatternBuilder.php:
--------------------------------------------------------------------------------
1 | |null */
10 | private $headers;
11 | /** @var string */
12 | private $name;
13 | /** @var string */
14 | private $matchingType = MultipartValuePattern::ANY;
15 |
16 | /**
17 | * @param ValueMatchingStrategy $valueMatchingStrategy
18 | * @return MultipartValuePatternBuilder
19 | */
20 | public function withMultipartBody($valueMatchingStrategy)
21 | {
22 | $this->bodyPatterns[] = $valueMatchingStrategy;
23 | return $this;
24 | }
25 |
26 | /**
27 | * @param string $name
28 | * @return MultipartValuePatternBuilder
29 | */
30 | public function withName($name)
31 | {
32 | $this->name = $name;
33 | $this->withHeader('Content-Disposition', WireMock::containing("name=\"$name\""));
34 | return $this;
35 | }
36 |
37 | /**
38 | * @param string $headerName
39 | * @param ValueMatchingStrategy $valueMatchingStrategy
40 | * @return MultipartValuePatternBuilder
41 | */
42 | public function withHeader($headerName, $valueMatchingStrategy)
43 | {
44 | $this->headers[$headerName] = $valueMatchingStrategy;
45 | return $this;
46 | }
47 |
48 | /**
49 | * @param string $type
50 | * @return MultipartValuePatternBuilder
51 | */
52 | public function matchingType($type)
53 | {
54 | $this->matchingType = $type;
55 | return $this;
56 | }
57 |
58 | public function build()
59 | {
60 | return new MultipartValuePattern(
61 | $this->bodyPatterns,
62 | $this->headers,
63 | $this->name,
64 | $this->matchingType
65 | );
66 | }
67 | }
--------------------------------------------------------------------------------
/test/WireMock/Integration/ProxyingIntegrationTest.php:
--------------------------------------------------------------------------------
1 | stubFor(WireMock::get(WireMock::urlEqualTo('/some/url'))
13 | ->willReturn(WireMock::aResponse()->proxiedFrom('http://otherhost.com/approot'))
14 | );
15 |
16 | // then
17 | assertThat($stubMapping->getResponse()->getProxyBaseUrl(), is('http://otherhost.com/approot'));
18 | assertThatTheOnlyMappingPresentIs($stubMapping);
19 | }
20 |
21 | public function testAdditionProxiedRequestHeadersCanBeSet()
22 | {
23 | // when
24 | $stubMapping = self::$_wireMock->stubFor(WireMock::get(WireMock::urlEqualTo('/some/url'))
25 | ->willReturn(
26 | WireMock::aResponse()->proxiedFrom('http://otherhost.com/approot')
27 | ->withAdditionalRequestHeader('X-Header', 'val')
28 | )
29 | );
30 |
31 | // then
32 | assertThat($stubMapping->getResponse()->getAdditionalProxyRequestHeaders(), equalTo(array('X-Header' => 'val')));
33 | assertThatTheOnlyMappingPresentIs($stubMapping);
34 | }
35 |
36 | public function testProxyUrlPrefixToRemoveCanBeSet()
37 | {
38 | // when
39 | $stubMapping = self::$_wireMock->stubFor(WireMock::get(WireMock::urlEqualTo("/other/service/doc/123"))
40 | ->willReturn(WireMock::aResponse()
41 | ->proxiedFrom("http://otherhost.com/approot")
42 | ->withProxyUrlPrefixToRemove("/other/service")));
43 |
44 | // then
45 | assertThat($stubMapping->getResponse()->getProxyUrlPrefixToRemove(), equalTo('/other/service'));
46 | assertThatTheOnlyMappingPresentIs($stubMapping);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/WireMock/Client/ServeEvent.php:
--------------------------------------------------------------------------------
1 | id = $id;
36 | $this->request = $request;
37 | $this->stubMapping = $stubMapping;
38 | $this->responseDefinition = $responseDefinition;
39 | $this->response = $response;
40 | }
41 |
42 | /**
43 | * @return string
44 | */
45 | public function getId()
46 | {
47 | return $this->id;
48 | }
49 |
50 | /**
51 | * @return LoggedRequest
52 | */
53 | public function getRequest()
54 | {
55 | return $this->request;
56 | }
57 |
58 | /**
59 | * @return StubMapping
60 | */
61 | public function getStubMapping()
62 | {
63 | return $this->stubMapping;
64 | }
65 |
66 | /**
67 | * @return ResponseDefinition
68 | */
69 | public function getResponseDefinition()
70 | {
71 | return $this->responseDefinition;
72 | }
73 |
74 | /**
75 | * @return LoggedResponse
76 | */
77 | public function getResponse()
78 | {
79 | return $this->response;
80 | }
81 | }
--------------------------------------------------------------------------------
/src/WireMock/Stubbing/StubImportBuilder.php:
--------------------------------------------------------------------------------
1 | build();
24 | $this->mappings[] = $mapping;
25 | return $this;
26 | }
27 |
28 | /**
29 | * @return StubImportBuilder
30 | */
31 | public function ignoreExisting()
32 | {
33 | $this->duplicatePolicy = StubImportOptions::IGNORE;
34 | return $this;
35 | }
36 |
37 | /**
38 | * @return StubImportBuilder
39 | */
40 | public function overwriteExisting()
41 | {
42 | $this->duplicatePolicy = StubImportOptions::OVERWRITE;
43 | return $this;
44 | }
45 |
46 | /**
47 | * @return StubImportBuilder
48 | */
49 | public function deleteAllExistingStubsNotInImport()
50 | {
51 | $this->deleteAllNotInImport = true;
52 | return $this;
53 | }
54 |
55 | /**
56 | * @return StubImportBuilder
57 | */
58 | public function doNotDeleteExistingStubs()
59 | {
60 | $this->deleteAllNotInImport = false;
61 | return $this;
62 | }
63 |
64 | /**
65 | * @return StubImport
66 | */
67 | public function build()
68 | {
69 | return new StubImport(
70 | $this->mappings,
71 | new StubImportOptions($this->duplicatePolicy, $this->deleteAllNotInImport)
72 | );
73 | }
74 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/HttpWait.php:
--------------------------------------------------------------------------------
1 | getMessage();
17 | continue;
18 | }
19 |
20 | if (isset($headers) && isset($headers[0]) && strpos($headers[0], '200 OK') !== false) {
21 | $serverStarted = true;
22 | break;
23 | } else {
24 | if (!isset($headers)) {
25 | $debugTrace[] = "$url not yet up. \$headers not set";
26 | } else if (!isset($headers[0])) {
27 | $debugTrace[] = "$url not yet up. \$headers[0] not set";
28 | } else {
29 | $debugTrace[] = "$url not yet up. \$headers[0] was {$headers[0]}";
30 | }
31 | }
32 | usleep(100000);
33 | }
34 | if (!$serverStarted) {
35 | $time = microtime(true) - $startTime;
36 | if ($debug) {
37 | echo implode("\n", $debugTrace) ."\n";
38 | }
39 | echo "$url failed to come up after $time seconds";
40 |
41 | }
42 | return $serverStarted;
43 | }
44 |
45 | public function waitForServerToFailToRespond($url, $timeoutSecs = 5)
46 | {
47 | $startTime = microtime(true);
48 | $serverFailedToRespond = false;
49 | while (microtime(true) - $startTime < $timeoutSecs) {
50 | if (@get_headers($url, 1) === false) {
51 | $serverFailedToRespond = true;
52 | break;
53 | }
54 | }
55 | return $serverFailedToRespond;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/WireMock/Serde/PropNaming/ReferencingPropertyNamingStrategy.php:
--------------------------------------------------------------------------------
1 | namingPropertyName = $namingPropertyName;
28 | $this->possibleNamesGenerator = $possibleNamesGenerator;
29 | StaticFactoryMethodValidator::validate($possibleNamesGenerator);
30 | }
31 |
32 | function getSerializedName(array $data): string
33 | {
34 | if (!array_key_exists($this->namingPropertyName, $data)) {
35 | throw new SerializationException("Cannot name property based on value of $this->namingPropertyName, because it is missing from data");
36 | }
37 | $value = $data[$this->namingPropertyName];
38 | if (!is_string($value)) {
39 | throw new SerializationException("Cannot name property based on value of $this->namingPropertyName, because that value is of type " . gettype($value));
40 | }
41 | return $value;
42 | }
43 |
44 | /**
45 | * @return string[]
46 | * @throws ReflectionException
47 | */
48 | function getPossibleSerializedNames(): array
49 | {
50 | $refMethod = MethodFactory::createMethod($this->possibleNamesGenerator);
51 | $refMethod->setAccessible(true);
52 | return $refMethod->invoke(null);
53 | }
54 | }
--------------------------------------------------------------------------------
/test/WireMock/Integration/TestClient.php:
--------------------------------------------------------------------------------
1 | _hostname = $_hostname;
14 | $this->_port = $_port;
15 | }
16 |
17 | public function get($path, array $headers = array(), $includeResponseHeaders = false)
18 | {
19 | $ch = curl_init($this->_makeUrl($path));
20 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
21 | if ($includeResponseHeaders) {
22 | curl_setopt($ch, CURLOPT_HEADER, true);
23 | }
24 | if (!empty($headers)) {
25 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
26 | }
27 |
28 | $result = $this->_makeTimedRequest($ch);
29 |
30 | curl_close($ch);
31 |
32 | return $result;
33 | }
34 |
35 | public function post($path, $body)
36 | {
37 | $ch = curl_init($this->_makeUrl($path));
38 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
39 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
40 | curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
41 |
42 | $result = $this->_makeTimedRequest($ch);
43 |
44 | curl_close($ch);
45 |
46 | return $result;
47 | }
48 |
49 | /**
50 | * @return float|null
51 | */
52 | public function getLastRequestTimeMillis()
53 | {
54 | return $this->_lastRequestTimeMillis;
55 | }
56 |
57 | private function _makeUrl($path)
58 | {
59 | if (strpos($path, '/') !== 0) {
60 | $path = '/' . $path;
61 | }
62 | return "http://$this->_hostname:$this->_port$path";
63 | }
64 |
65 | private function _makeTimedRequest($ch)
66 | {
67 | $startTime = microtime(true);
68 | $result = curl_exec($ch);
69 | $endTime = microtime(true);
70 | $this->_lastRequestTimeMillis = ($endTime - $startTime) * 1000;
71 |
72 | return $result;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/WireMock/Client/EqualToXmlMatchingStrategy.php:
--------------------------------------------------------------------------------
1 | enablePlaceholders = $enablePlaceholders;
29 | $this->placeholderOpeningDelimiterRegex = $placeholderOpeningDelimiterRegex;
30 | $this->placeholderClosingDelimiterRegex = $placeholderClosingDelimiterRegex;
31 | }
32 |
33 | /**
34 | * @param string $comparisonTypes...
35 | * @return $this
36 | */
37 | public function exemptingComparisons($comparisonTypes)
38 | {
39 | $comparisonTypes = func_get_args();
40 | $this->exemptedComparisons = $comparisonTypes;
41 | return $this;
42 | }
43 |
44 | /**
45 | * @return bool
46 | */
47 | public function isEnablePlaceholders(): bool
48 | {
49 | return $this->enablePlaceholders;
50 | }
51 |
52 | /**
53 | * @return string|null
54 | */
55 | public function getPlaceholderOpeningDelimiterRegex(): ?string
56 | {
57 | return $this->placeholderOpeningDelimiterRegex;
58 | }
59 |
60 | /**
61 | * @return string|null
62 | */
63 | public function getPlaceholderClosingDelimiterRegex(): ?string
64 | {
65 | return $this->placeholderClosingDelimiterRegex;
66 | }
67 |
68 | /**
69 | * @return string[]|null
70 | */
71 | public function getExemptedComparisons(): ?array
72 | {
73 | return $this->exemptedComparisons;
74 | }
75 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/Curl.php:
--------------------------------------------------------------------------------
1 | makeCurlRequest('GET', $url);
15 | }
16 |
17 | /**
18 | * @param string $url
19 | * @param string|null $body The request body
20 | * @return string The response body
21 | * @throws ClientException
22 | */
23 | public function post(string $url, ?string $body = null): string
24 | {
25 | return $this->makeCurlRequest('POST', $url, $body);
26 | }
27 |
28 | /**
29 | * @param string $url
30 | * @param array|string|null $body The request body
31 | * @return string The response body
32 | * @throws ClientException
33 | */
34 | public function put(string $url, ?string $body = null): string
35 | {
36 | return $this->makeCurlRequest('PUT', $url, $body);
37 | }
38 |
39 | /**
40 | * @param string $url
41 | * @return string The response body
42 | * @throws ClientException
43 | */
44 | public function delete(string $url): string
45 | {
46 | return $this->makeCurlRequest('DELETE', $url);
47 | }
48 |
49 | /**
50 | * @throws ClientException
51 | */
52 | private function makeCurlRequest(string $method, string $url, ?string $json = null)
53 | {
54 | $ch = curl_init($url);
55 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
56 | if ($json !== null) {
57 | curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
58 | $contentLength = strlen($json);
59 | } else {
60 | $contentLength = 0;
61 | }
62 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
63 | curl_setopt($ch, CURLOPT_HTTPHEADER, array(
64 | 'Content-Type: application/json',
65 | "Content-Length: $contentLength",
66 | ));
67 |
68 | $result = curl_exec($ch);
69 |
70 | $responseCode = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
71 | if ($responseCode < 200 || $responseCode >= 300) {
72 | throw new ClientException($responseCode, $result);
73 | }
74 |
75 | curl_close($ch);
76 |
77 | return $result;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/WireMock/Client/LoggedRequest.php:
--------------------------------------------------------------------------------
1 | */
16 | private $headers;
17 | /** @var array */
18 | private $cookies;
19 | /** @var string */
20 | private $body;
21 | /** @var string */
22 | private $bodyAsBase64;
23 | /** @var bool */
24 | private $browserProxyRequest;
25 | /** @var int */
26 | private $loggedDate;
27 | /** @var string */
28 | private $loggedDateString;
29 |
30 | /**
31 | * @return string
32 | */
33 | public function getUrl()
34 | {
35 | return $this->url;
36 | }
37 |
38 | /**
39 | * @return string
40 | */
41 | public function getAbsoluteUrl()
42 | {
43 | return $this->absoluteUrl;
44 | }
45 |
46 | /**
47 | * @return string
48 | */
49 | public function getMethod()
50 | {
51 | return $this->method;
52 | }
53 |
54 | /**
55 | * @return string
56 | */
57 | public function getClientIp()
58 | {
59 | return $this->clientIp;
60 | }
61 |
62 | /**
63 | * @return array
64 | */
65 | public function getHeaders()
66 | {
67 | return $this->headers;
68 | }
69 |
70 | /**
71 | * @return array
72 | */
73 | public function getCookies()
74 | {
75 | return $this->cookies;
76 | }
77 |
78 | /**
79 | * @return string
80 | */
81 | public function getBody()
82 | {
83 | return $this->body;
84 | }
85 |
86 | /**
87 | * @return string
88 | */
89 | public function getBodyAsBase64()
90 | {
91 | return $this->bodyAsBase64;
92 | }
93 |
94 | /**
95 | * @return boolean
96 | */
97 | public function isBrowserProxyRequest()
98 | {
99 | return $this->browserProxyRequest;
100 | }
101 |
102 | /**
103 | * @return int
104 | */
105 | public function getLoggedDate()
106 | {
107 | return $this->loggedDate;
108 | }
109 |
110 | /**
111 | * @return string
112 | */
113 | public function getLoggedDateString()
114 | {
115 | return $this->loggedDateString;
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/test/WireMock/Matching/RequestPatternTest.php:
--------------------------------------------------------------------------------
1 | getMethod(), is($method));
20 | assertThat($requestPattern->getUrlMatchingStrategy(), is($urlMatchingStrategy));
21 | }
22 |
23 | public function testRequestHeaderMatchersAreAvailable()
24 | {
25 | // given
26 | $headers = array('aHeader' => WireMock::equalTo('aValue'));
27 | $requestPattern = new RequestPattern(
28 | 'GET',
29 | new UrlMatchingStrategy('url', '/some/url'),
30 | $headers
31 | );
32 |
33 | // then
34 | assertThat($requestPattern->getHeaders(), is($headers));
35 | }
36 |
37 | public function testRequestCookieMatchersAreAvailable()
38 | {
39 | // given
40 | $cookies = array('aCookie' => WireMock::equalTo('aValue'));
41 | $requestPattern = new RequestPattern(
42 | 'GET',
43 | new UrlMatchingStrategy('url', '/some/url'),
44 | null,
45 | $cookies
46 | );
47 |
48 | // then
49 | assertThat($requestPattern->getCookies(), is($cookies));
50 | }
51 |
52 | public function testRequestBodyMatchersAreAvailable()
53 | {
54 | // given
55 | $bodyPatterns = array(WireMock::equalTo('aValue'));
56 | $requestPattern = new RequestPattern(
57 | 'GET',
58 | new UrlMatchingStrategy('url', '/some/url'),
59 | null,
60 | null,
61 | $bodyPatterns
62 | );
63 |
64 | // then
65 | assertThat($requestPattern->getBodyPatterns(), is($bodyPatterns));
66 | }
67 |
68 | public function testQueryParamMatchersAreAvailable()
69 | {
70 | // given
71 | $queryParams = array('aParam' => WireMock::equalTo('aValue'));
72 | $requestPattern = new RequestPattern(
73 | 'GET',
74 | new UrlMatchingStrategy('url', '/some/url'),
75 | null,
76 | null,
77 | null,
78 | null,
79 | $queryParams
80 | );
81 |
82 | // then
83 | assertThat($requestPattern->getQueryParameters(), is($queryParams));
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/WireMock/SerdeGen/WireMockSerdeGen.php:
--------------------------------------------------------------------------------
1 | since = $since;
25 | return $this;
26 | }
27 |
28 | /**
29 | * @param int $limit
30 | * @return $this
31 | */
32 | public function withLimit($limit)
33 | {
34 | $this->limit = $limit;
35 | return $this;
36 | }
37 |
38 | /**
39 | * @return $this
40 | */
41 | public function withUnmatched()
42 | {
43 | $this->unmatched = true;
44 | return $this;
45 | }
46 |
47 | /**
48 | * @param string $stubId
49 | * @return $this
50 | */
51 | public function withStubMapping($stubId)
52 | {
53 | $this->matchingStubId = $stubId;
54 | return $this;
55 | }
56 |
57 | public function toParamsString()
58 | {
59 | $params = [];
60 | if ($this->since) {
61 | $params[] = 'since=' . urlencode($this->since->format(DateTime::ATOM));
62 | }
63 | if ($this->limit) {
64 | $params[] = 'limit=' . urlencode($this->limit);
65 | }
66 | if ($this->unmatched) {
67 | $params[] = 'unmatched=true';
68 | }
69 | if ($this->matchingStubId) {
70 | $params[] = 'matchingStub=' . urlencode($this->matchingStubId);
71 | }
72 | return join('&', $params);
73 | }
74 |
75 | /**
76 | * @param DateTime|null $since
77 | * @param int|null $limit
78 | * @return self
79 | */
80 | public static function paginated($since, $limit = null)
81 | {
82 | $result = new self();
83 | if ($since) {
84 | $result->withSince($since);
85 | }
86 | if ($limit) {
87 | $result->withLimit($limit);
88 | }
89 | return $result;
90 | }
91 |
92 | /**
93 | * @return self
94 | */
95 | public static function unmatched()
96 | {
97 | $result = new self();
98 | return $result->withUnmatched();
99 | }
100 |
101 | /**
102 | * @param string $stubId
103 | * @return self
104 | */
105 | public static function forStubMapping($stubId)
106 | {
107 | $result = new self();
108 | return $result->withStubMapping($stubId);
109 | }
110 | }
--------------------------------------------------------------------------------
/test/WireMock/Serde/SerializerTest.php:
--------------------------------------------------------------------------------
1 | normalize($primitiveValue);
19 |
20 | assertThat($normalized, is($primitiveValue));
21 | }
22 |
23 | public function testNormalizingObjectRegisteredInLookupDelegatesToSerdeTypeClass()
24 | {
25 | $mockSerdeType = Phake::mock(SerdeTypeClass::class);
26 | $serializer = new Serializer(new SerdeTypeLookup([self::class => $mockSerdeType], []));
27 | Phake::when($mockSerdeType)->normalize($this, $serializer)->thenReturn(['dummy']);
28 |
29 | $normalized = $serializer->normalize($this);
30 |
31 | assertThat($normalized, is(['dummy']));
32 | }
33 |
34 | public function testSerializingObjectNotInLookupObservesJsonSerializableInterface()
35 | {
36 | $object = new class implements JsonSerializable {
37 | public function jsonSerialize(): array
38 | {
39 | return ['foo' => 'bar'];
40 | }
41 | };
42 | $mockSerdeType = Phake::mock(SerdeTypeClass::class);
43 | $serializer = new Serializer(new SerdeTypeLookup([self::class => $mockSerdeType], [self::class => true]));
44 | Phake::when($mockSerdeType)->normalize($this, $serializer)->thenReturn(['unregistered' => [$object]]);
45 |
46 | $json = $serializer->serialize($this);
47 |
48 | self::assertEquals('{"unregistered":[{"foo":"bar"}]}', $json);
49 | }
50 |
51 | public function testNormalizingArrayRecursivelyDenormalizesKeepingKeys()
52 | {
53 | $mockSerdeType = Phake::mock(SerdeTypeClass::class);
54 | $serializer = new Serializer(new SerdeTypeLookup([self::class => $mockSerdeType], []));
55 | Phake::when($mockSerdeType)->normalize($this, $serializer)->thenReturn(['dummy']);
56 |
57 | $normalized = $serializer->normalize(['one' => $this, 'two' => 123]);
58 |
59 | assertThat($normalized, is(['one' => ['dummy'], 'two' => 123]));
60 | }
61 |
62 | public function testDenormalizingDelegatesToSerdeType()
63 | {
64 | $mockSerdeType = Phake::mock(SerdeTypeClass::class);
65 | $serializer = new Serializer(new SerdeTypeLookup([self::class => $mockSerdeType], []));
66 | $data = ['dummy'];
67 | Phake::when($mockSerdeType)->denormalize($data, [])->thenReturn($this);
68 |
69 | $denormalized = $serializer->denormalize($data, self::class);
70 |
71 | assertThat($denormalized, is($this));
72 | }
73 |
74 | public function providerPrimitives(): array
75 | {
76 | return [
77 | 'string' => ['a string'],
78 | 'int' => [123],
79 | 'float' => [1.23],
80 | 'bool' => [false],
81 | 'null' => [null],
82 | ];
83 | }
84 | }
--------------------------------------------------------------------------------
/test/WireMock/Serde/Type/SerdeTypePrimitiveTest.php:
--------------------------------------------------------------------------------
1 | false,
11 | 'boolean' => false,
12 | 'int' => 123,
13 | 'integer' => 123,
14 | 'float' => 1.23,
15 | 'double' => 1.23,
16 | 'string' => 'a string',
17 | ];
18 | private const EQUIVALENT_TYPES = [
19 | 'bool' => 'boolean',
20 | 'boolean' => 'bool',
21 | 'int' => 'integer',
22 | 'integer' => 'int',
23 | 'float' => 'double',
24 | 'double' => 'float'
25 | ];
26 |
27 | /** @dataProvider providerMatchedTypeAndData */
28 | public function testDenormalizingCorrectTypeDataIsANoOp(string $type, $data)
29 | {
30 | $serdeType = new SerdeTypePrimitive($type);
31 | $denormalized = $serdeType->denormalize($data, []);
32 | assertThat($denormalized, is($data));
33 | }
34 |
35 | /** @dataProvider providerMismatchedTypeAndData */
36 | public function testDenormalizingMismatchedTypeDataThrows(string $type, $data)
37 | {
38 | $this->expectExceptionMessage('Cannot deserialize data of type');
39 | $serdeType = new SerdeTypePrimitive($type);
40 | $serdeType->denormalize($data, []);
41 | }
42 |
43 | /** @dataProvider providerMatchedTypeAndData */
44 | public function testDenormalizingObjectDataThrows(string $type)
45 | {
46 | $this->expectExceptionMessage('Cannot deserialize data of type');
47 | $serdeType = new SerdeTypePrimitive($type);
48 | $serdeType->denormalize($this, []);
49 | }
50 |
51 | /** @dataProvider providerMatchedTypeAndData */
52 | public function testDenormalizingArrayDataThrows(string $type)
53 | {
54 | $this->expectExceptionMessage('Cannot deserialize data of type');
55 | $serdeType = new SerdeTypePrimitive($type);
56 | $data = [];
57 | $serdeType->denormalize($data, []);
58 | }
59 |
60 | /** @dataProvider providerMatchedTypeAndData */
61 | public function testDenormalizingNullDataThrows(string $type)
62 | {
63 | $this->expectExceptionMessage('Cannot deserialize data of type');
64 | $serdeType = new SerdeTypePrimitive($type);
65 | $data = null;
66 | $serdeType->denormalize($data, []);
67 | }
68 |
69 | public function providerMatchedTypeAndData(): array
70 | {
71 | $result = [];
72 | foreach (self::EXAMPLE_DATA as $type => $data) {
73 | $result[$type] = [$type, $data];
74 | }
75 | return $result;
76 | }
77 |
78 | public function providerMismatchedTypeAndData(): array
79 | {
80 | $result = [];
81 | foreach (self::EXAMPLE_DATA as $type => $ignoredData) {
82 | foreach (self::EXAMPLE_DATA as $otherType => $data) {
83 | if ($type === $otherType || (isset(self::EQUIVALENT_TYPES[$type]) && self::EQUIVALENT_TYPES[$type] === $otherType)) {
84 | continue;
85 | }
86 | $result["$type with $otherType data"] = [$type, $data];
87 | }
88 | }
89 | return $result;
90 | }
91 | }
--------------------------------------------------------------------------------
/test/WireMock/Integration/NearMissesIntegrationTest.php:
--------------------------------------------------------------------------------
1 | stubFor(WireMock::get(WireMock::urlEqualTo('/some-url'))
13 | ->willReturn(WireMock::aResponse()));
14 | $this->_testClient->get('/different-url');
15 | $loggedRequests = self::$_wireMock->findUnmatchedRequests()->getRequests();
16 | $loggedRequest = $loggedRequests[0];
17 |
18 | // when
19 | $nearMissesResult = self::$_wireMock->findNearMissesFor($loggedRequest);
20 |
21 | // then
22 | $nearMisses = $nearMissesResult->getNearMisses();
23 | $nearMiss = $nearMisses[0];
24 | assertThat($nearMiss->getRequest()->getUrl(), equalTo('/different-url'));
25 | assertThat($nearMiss->getMapping()->getRequest()->getUrlMatchingStrategy()->getMatchingValue(), equalTo('/some-url'));
26 | assertThat($nearMiss->getRequestPattern(), nullValue());
27 | assertThat($nearMiss->getMatchResult()->getDistance(), floatValue());
28 | }
29 |
30 | public function testFindNearMissesForRequestPattern()
31 | {
32 | // given
33 | $requestPattern = WireMock::getRequestedFor(WireMock::urlEqualTo('/some-url'));
34 | $this->_testClient->get('/different-url');
35 |
36 | // when
37 | $nearMissesResult = self::$_wireMock->findNearMissesFor($requestPattern);
38 |
39 | // then
40 | $nearMisses = $nearMissesResult->getNearMisses();
41 | $nearMiss = $nearMisses[0];
42 | assertThat($nearMiss->getRequest()->getUrl(), equalTo('/different-url'));
43 | assertThat($nearMiss->getMapping(), nullValue());
44 | assertThat($nearMiss->getRequestPattern()->getUrlMatchingStrategy()->getMatchingValue(), equalTo('/some-url'));
45 | assertThat($nearMiss->getMatchResult()->getDistance(), floatValue());
46 | }
47 |
48 | public function testFindNearMissesForAllUnmatched()
49 | {
50 | // given
51 | self::$_wireMock->stubFor(WireMock::get(WireMock::urlEqualTo('/some-url1'))
52 | ->willReturn(WireMock::aResponse()));
53 | self::$_wireMock->stubFor(WireMock::get(WireMock::urlEqualTo('/some-url2'))
54 | ->willReturn(WireMock::aResponse()));
55 | self::$_wireMock->stubFor(WireMock::get(WireMock::urlEqualTo('/some-url3'))
56 | ->willReturn(WireMock::aResponse()));
57 | self::$_wireMock->stubFor(WireMock::get(WireMock::urlEqualTo('/some-url4'))
58 | ->willReturn(WireMock::aResponse()));
59 | $this->_testClient->get('/different-url');
60 |
61 | // when
62 | $nearMissesResult = self::$_wireMock->findNearMissesForAllUnmatched();
63 |
64 | // then
65 | $nearMisses = $nearMissesResult->getNearMisses();
66 | assertThat($nearMisses, arrayWithSize(3));
67 | $nearMiss = $nearMisses[0];
68 | assertThat($nearMiss->getRequest()->getUrl(), equalTo('/different-url'));
69 | assertThat($nearMiss->getMapping()->getRequest()->getUrlMatchingStrategy()->getMatchingValue(), startsWith('/some-url'));
70 | assertThat($nearMiss->getRequestPattern(), nullValue());
71 | assertThat($nearMiss->getMatchResult()->getDistance(), floatValue());
72 | }
73 | }
--------------------------------------------------------------------------------
/test/WireMock/Integration/WebhookIntegrationTest.php:
--------------------------------------------------------------------------------
1 | stubFor(WireMock::post(WireMock::urlPathEqualTo("/something-async"))
14 | ->willReturn(WireMock::ok())
15 | ->withPostServeAction("webhook", WireMock::webhook()
16 | ->withMethod(RequestMethod::POST)
17 | ->withUrl("http://my-target-host/callback")
18 | ->withHeader("Content-Type", "application/json")
19 | ->withBody("{ \"result\": \"SUCCESS\" }"))
20 | );
21 |
22 | // then
23 | assertThatTheOnlyMappingPresentIs($stubMapping);
24 | }
25 |
26 | public function testWebhookCallbackWithBase64Body()
27 | {
28 | // when
29 | $packedResponseBody = pack('c*', 0x23, 0x59, 0x11);
30 | $stubMapping = self::$_wireMock->stubFor(WireMock::post(WireMock::urlPathEqualTo("/something-async"))
31 | ->willReturn(WireMock::ok())
32 | ->withPostServeAction("webhook", WireMock::webhook()
33 | ->withMethod(RequestMethod::POST)
34 | ->withUrl("http://my-target-host/callback")
35 | ->withHeader("Content-Type", "application/json")
36 | ->withBodyData($packedResponseBody))
37 | );
38 |
39 | // then
40 | assertThatTheOnlyMappingPresentIs($stubMapping);
41 | }
42 |
43 | public function testWebhookCallbackWithFixedDelay()
44 | {
45 | // when
46 | $stubMapping = self::$_wireMock->stubFor(WireMock::post(WireMock::urlPathEqualTo("/delayed"))
47 | ->willReturn(WireMock::ok())
48 | ->withPostServeAction("webhook", WireMock::webhook()
49 | ->withFixedDelay(1000)
50 | ->withMethod(RequestMethod::GET)
51 | ->withUrl("http://my-target-host/callback")
52 | )
53 | );
54 |
55 | // then
56 | assertThatTheOnlyMappingPresentIs($stubMapping);
57 | }
58 |
59 | public function testWebhookCallbackWithUniformRandomDelay()
60 | {
61 | // when
62 | $stubMapping = self::$_wireMock->stubFor(WireMock::post(WireMock::urlPathEqualTo("/delayed"))
63 | ->willReturn(WireMock::ok())
64 | ->withPostServeAction("webhook", WireMock::webhook()
65 | ->withUniformRandomDelay(500, 1000)
66 | ->withMethod(RequestMethod::GET)
67 | ->withUrl("http://my-target-host/callback")
68 | )
69 | );
70 |
71 | // then
72 | assertThatTheOnlyMappingPresentIs($stubMapping);
73 | }
74 |
75 | public function testWebhookCallbackWithTemplatingBasedOnExtraParameter()
76 | {
77 | // when
78 | $stubMapping = self::$_wireMock->stubFor(WireMock::post(WireMock::urlPathEqualTo("/templating"))
79 | ->willReturn(WireMock::ok())
80 | ->withPostServeAction("webhook", WireMock::webhook()
81 | ->withMethod(RequestMethod::GET)
82 | ->withUrl("http://my-target-host/callback")
83 | ->withHeader("X-Multi", "{{parameters.one}}")
84 | ->withExtraParameter("one", "param-one-value")
85 | )
86 | );
87 |
88 | // then
89 | assertThatTheOnlyMappingPresentIs($stubMapping);
90 | }
91 | }
--------------------------------------------------------------------------------
/test/WireMock/Integration/MultipartIntegrationTest.php:
--------------------------------------------------------------------------------
1 | stubFor(WireMock::post(WireMock::anyUrl())
14 | ->withMultipartRequestBody(WireMock::aMultipart()->withMultipartBody(WireMock::matching('abc')))
15 | ->withMultipartRequestBody(WireMock::aMultipart()->withMultipartBody(WireMock::matching('def')))
16 | ->willReturn(WireMock::aResponse())
17 | );
18 |
19 | // then
20 | assertThatTheOnlyMappingPresentIs($stubbing);
21 | assertThat($stubbing->getRequest()->getMultipartPatterns(), arrayWithSize(2));
22 | $patterns = $stubbing->getRequest()->getMultipartPatterns();
23 | assertThat($patterns[0]->getBodyPatterns()[0], equalTo(WireMock::matching('abc')));
24 | assertThat($patterns[1]->getBodyPatterns()[0], equalTo(WireMock::matching('def')));
25 | }
26 |
27 | public function testMultipartWithNameCanBeRegistered()
28 | {
29 | // when
30 | $stubbing = self::$_wireMock->stubFor(WireMock::post(WireMock::anyUrl())
31 | ->withMultipartRequestBody(WireMock::aMultipart()->withName('partName'))
32 | ->willReturn(WireMock::aResponse())
33 | );
34 |
35 | // then
36 | assertThatTheOnlyMappingPresentIs($stubbing);
37 | $patterns = $stubbing->getRequest()->getMultipartPatterns();
38 | assertThat($patterns[0]->getHeaders()['Content-Disposition'], equalTo(WireMock::containing('name="partName"')));
39 | }
40 |
41 | public function testMultipartWithHeaderCanBeRegistered()
42 | {
43 | // when
44 | $stubbing = self::$_wireMock->stubFor(WireMock::post(WireMock::anyUrl())
45 | ->withMultipartRequestBody(WireMock::aMultipart()->withHeader('X-Header', WireMock::containing('foo')))
46 | ->willReturn(WireMock::aResponse())
47 | );
48 |
49 | // then
50 | assertThatTheOnlyMappingPresentIs($stubbing);
51 | $patterns = $stubbing->getRequest()->getMultipartPatterns();
52 | assertThat($patterns[0]->getHeaders()['X-Header'], equalTo(WireMock::containing('foo')));
53 | }
54 |
55 | public function testMultipartMatchingTypeDefaultsToAny()
56 | {
57 | // when
58 | $stubbing = self::$_wireMock->stubFor(WireMock::post(WireMock::anyUrl())
59 | ->withMultipartRequestBody(WireMock::aMultipart())
60 | ->willReturn(WireMock::aResponse())
61 | );
62 |
63 | // then
64 | assertThatTheOnlyMappingPresentIs($stubbing);
65 | $patterns = $stubbing->getRequest()->getMultipartPatterns();
66 | assertThat($patterns[0]->getMatchingType(), equalTo(MultipartValuePattern::ANY));
67 | }
68 |
69 | public function testMultipartMatchingTypeCanBetSetToAll()
70 | {
71 | // when
72 | $stubbing = self::$_wireMock->stubFor(WireMock::post(WireMock::anyUrl())
73 | ->withMultipartRequestBody(WireMock::aMultipart()->matchingType(MultipartValuePattern::ALL))
74 | ->willReturn(WireMock::aResponse())
75 | );
76 |
77 | // then
78 | assertThatTheOnlyMappingPresentIs($stubbing);
79 | $patterns = $stubbing->getRequest()->getMultipartPatterns();
80 | assertThat($patterns[0]->getMatchingType(), equalTo(MultipartValuePattern::ALL));
81 | }
82 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/SerdeProp.php:
--------------------------------------------------------------------------------
1 | name = $name;
47 | $this->owningClassName = $owningClassName;
48 | $this->serdeType = $serdeType;
49 | $this->propertyNamingStrategy = $propertyNamingStrategy;
50 | $this->unwrapped = $unwrapped;
51 | $this->catchAll = $catchAll;
52 | $this->includeInNormalizedForm = true;
53 | }
54 |
55 | /**
56 | * @throws SerializationException
57 | */
58 | public function instantiateAndConsumeData(array &$data, array $path)
59 | {
60 | $path[] = $this->name;
61 | $name = $this->name;
62 | $propData = array_key_exists($name, $data) ? $data[$name] : null;
63 | unset($data[$name]);
64 | return $this->serdeType->denormalize($propData, $path);
65 | }
66 |
67 | /**
68 | * @throws ReflectionException
69 | */
70 | public function getData(object $object)
71 | {
72 | $refProp = new ReflectionProperty($this->owningClassName, $this->name);
73 | $refProp->setAccessible(true);
74 | return $refProp->getValue($object);
75 | }
76 |
77 | public function getSerializedName(array $data): string
78 | {
79 | if (!$this->propertyNamingStrategy) {
80 | return $this->name;
81 | }
82 | return $this->propertyNamingStrategy->getSerializedName($data);
83 | }
84 |
85 | public function getPossibleSerializedNames(): array
86 | {
87 | if ($this->propertyNamingStrategy !== null) {
88 | return $this->propertyNamingStrategy->getPossibleSerializedNames();
89 | } else {
90 | return [$this->name];
91 | }
92 | }
93 |
94 | /**
95 | * @return SerdeTypeClass
96 | * @throws SerializationException
97 | */
98 | public function getPotentiallyNullableSerdeTypeClassOrThrow(): SerdeTypeClass {
99 | if ($this->serdeType instanceof SerdeTypeClass) {
100 | return $this->serdeType;
101 | } elseif ($this->serdeType instanceof SerdeTypeUnion) {
102 | if ($this->serdeType->isNullableClass()) {
103 | return $this->serdeType->getClassTypeOrThrow();
104 | }
105 | }
106 | throw new SerializationException("Cannot get SerdeTypeClass for prop $this->name because it is of type " . $this->serdeType->displayName());
107 | }
108 | }
--------------------------------------------------------------------------------
/src/WireMock/PostServe/WebhookDefinition.php:
--------------------------------------------------------------------------------
1 | method = $method;
33 | return $this;
34 | }
35 |
36 | public function withUrl(string $url): self
37 | {
38 | $this->url = $url;
39 | return $this;
40 | }
41 |
42 | public function withHeader(string $header, string $value): self
43 | {
44 | $this->headers[$header] = $value;
45 | return $this;
46 | }
47 |
48 | public function withBody(string $body): self
49 | {
50 | $this->body = $body;
51 | return $this;
52 | }
53 |
54 | public function withBodyData(string $bytesAsString): self
55 | {
56 | $base64 = base64_encode($bytesAsString);
57 | $this->base64Body = $base64;
58 | return $this;
59 | }
60 |
61 | public function withFixedDelay(int $delayMillis): self
62 | {
63 | $this->delay = new FixedDelay($delayMillis);
64 | return $this;
65 | }
66 |
67 | public function withRandomDelay(DelayDistribution $delayDistribution): self
68 | {
69 | $this->delay = $delayDistribution;
70 | return $this;
71 | }
72 |
73 | public function withLogNormalRandomDelay(float $median, float $sigma): self
74 | {
75 | return $this->withRandomDelay(new LogNormal($median, $sigma));
76 | }
77 |
78 | public function withUniformRandomDelay(int $lower, int $upper): self
79 | {
80 | return $this->withRandomDelay(new UniformDistribution($lower, $upper));
81 | }
82 |
83 | public function withExtraParameter(string $name, $value): self
84 | {
85 | $this->extraParameters[$name] = $value;
86 | return $this;
87 | }
88 |
89 | // TODO: Split out getters and fluent builder methods into separate classes
90 |
91 | /**
92 | * @return string|null
93 | */
94 | public function getMethod(): ?string
95 | {
96 | return $this->method;
97 | }
98 |
99 | /**
100 | * @return string|null
101 | */
102 | public function getUrl(): ?string
103 | {
104 | return $this->url;
105 | }
106 |
107 | /**
108 | * @return string[]|null
109 | */
110 | public function getHeaders(): ?array
111 | {
112 | return $this->headers;
113 | }
114 |
115 | /**
116 | * @return string|null
117 | */
118 | public function getBody(): ?string
119 | {
120 | return $this->body;
121 | }
122 |
123 | /**
124 | * @return string|null
125 | */
126 | public function getBase64Body(): ?string
127 | {
128 | return $this->base64Body;
129 | }
130 |
131 | /**
132 | * @return DelayDistribution|null
133 | */
134 | public function getDelay(): ?DelayDistribution
135 | {
136 | return $this->delay;
137 | }
138 |
139 | /**
140 | * @return array|null
141 | */
142 | public function getExtraParameters(): ?array
143 | {
144 | return $this->extraParameters;
145 | }
146 | }
--------------------------------------------------------------------------------
/test/WireMock/Stubbing/StubMappingTest.php:
--------------------------------------------------------------------------------
1 | _serializer = SerializerFactory::default();
23 | $this->_mockRequestPattern = Phake::mock(RequestPattern::class);
24 | $this->_mockResponseDefinition = Phake::mock(ResponseDefinition::class);
25 | }
26 |
27 | private function toArray($obj)
28 | {
29 | return $this->_serializer->normalize($obj);
30 | }
31 |
32 | public function testRequestPatternAndResponseDefinitionAreAvailableInArray()
33 | {
34 | // given
35 | $stubMapping = new StubMapping(
36 | new RequestPattern('GET', WireMock::anyUrl()),
37 | new ResponseDefinition(200)
38 | );
39 |
40 | // when
41 | $stubMappingArray = $this->toArray($stubMapping);
42 |
43 | // then
44 | assertThat($stubMappingArray, hasEntry('request', $this->toArray($stubMapping->getRequest())));
45 | assertThat($stubMappingArray, hasEntry('response', $this->toArray($stubMapping->getResponse())));
46 | }
47 |
48 | public function testIdIsInArrayIfSpecified()
49 | {
50 | // given
51 | $stubMapping = new StubMapping(
52 | new RequestPattern('GET', WireMock::anyUrl()),
53 | new ResponseDefinition(200),
54 | 'some-long-guid'
55 | );
56 |
57 | // when
58 | $stubMappingArray = $this->toArray($stubMapping);
59 |
60 | // then
61 | assertThat($stubMappingArray, hasEntry('id', 'some-long-guid'));
62 | }
63 |
64 | public function testNameIsInArrayIfSpecified()
65 | {
66 | // given
67 | $stubMapping = new StubMapping(
68 | new RequestPattern('GET', WireMock::anyUrl()),
69 | new ResponseDefinition(200),
70 | null,
71 | 'stub-name'
72 | );
73 |
74 | // when
75 | $stubMappingArray = $this->toArray($stubMapping);
76 |
77 | // then
78 | assertThat($stubMappingArray, hasEntry('name', 'stub-name'));
79 | }
80 |
81 | public function testPriorityIsInArrayIfSpecified()
82 | {
83 | // given
84 | $stubMapping = new StubMapping(
85 | new RequestPattern('GET', WireMock::anyUrl()),
86 | new ResponseDefinition(200),
87 | null,
88 | null,
89 | 5
90 | );
91 |
92 | // when
93 | $stubMappingArray = $this->toArray($stubMapping);
94 |
95 | // then
96 | assertThat($stubMappingArray, hasEntry('priority', 5));
97 | }
98 |
99 | public function testScenarioArrayIsMergedIntoArrayIfSpecified()
100 | {
101 | // given
102 | $scenarioMapping = new ScenarioMapping('Some Scenario', 'from', 'to');
103 | $stubMapping = new StubMapping(
104 | new RequestPattern('GET', WireMock::anyUrl()),
105 | new ResponseDefinition(200),
106 | null,
107 | null,
108 | null,
109 | $scenarioMapping
110 | );
111 |
112 | // when
113 | $stubMappingArray = $this->toArray($stubMapping);
114 |
115 | // then
116 | assertThat($stubMappingArray, hasEntry('scenarioName', 'Some Scenario'));
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/WireMock/Serde/SerdeClassDefinition.php:
--------------------------------------------------------------------------------
1 | classDiscriminationInfo = $classDiscriminationInfo;
25 | $this->constructorArgProps = $constructorArgProps;
26 | $this->properties = $properties;
27 | }
28 |
29 | /**
30 | * @return SerdeProp[]
31 | */
32 | public function getConstructorArgProps(): array
33 | {
34 | return $this->constructorArgProps;
35 | }
36 |
37 | /**
38 | * @throws SerializationException
39 | */
40 | public function getPropertyByPhpName(string $name): ?SerdeProp
41 | {
42 | $matchingProps = array_filter($this->properties, function($prop) use ($name) {
43 | return $prop->name === $name;
44 | });
45 | if (count($matchingProps) === 0) {
46 | return null;
47 | } elseif (count($matchingProps) === 1) {
48 | return current($matchingProps);
49 | } else {
50 | throw new SerializationException("Expected 0 or 1 prop to match serialized name $name but found multiple");
51 | }
52 | }
53 |
54 | /**
55 | * @throws SerializationException
56 | */
57 | public function getCatchAllProp(): ?SerdeProp
58 | {
59 | $matchingProps = array_filter($this->properties, function($prop) {
60 | return $prop->catchAll;
61 | });
62 | if (count($matchingProps) === 0) {
63 | return null;
64 | } elseif (count($matchingProps) === 1) {
65 | return current($matchingProps);
66 | } else {
67 | throw new SerializationException("Expected 0 or 1 prop to be marked @serde-catch-all but found multiple");
68 | }
69 | }
70 |
71 | /**
72 | * @return SerdeProp[]
73 | */
74 | public function getAllPropertiesAndArgs(): array
75 | {
76 | return $this->properties;
77 | }
78 |
79 | public function isPossibleSerializedName(string $name): bool
80 | {
81 | foreach ($this->properties as $prop) {
82 | foreach ($prop->getPossibleSerializedNames() as $possibleName) {
83 | if ($name === $possibleName) {
84 | return true;
85 | }
86 | }
87 | }
88 | return false;
89 | }
90 |
91 | /**
92 | * @throws SerializationException
93 | */
94 | public function isPhpName(string $name): bool
95 | {
96 | return $this->getPropertyByPhpName($name) !== null;
97 | }
98 |
99 | /**
100 | * @throws ReflectionException
101 | */
102 | public function getDiscriminator(): ?ClassDiscriminator
103 | {
104 | if ($this->classDiscriminationInfo === null) {
105 | return null;
106 | }
107 | return $this->classDiscriminationInfo->getDiscriminator();
108 | }
109 |
110 | /**
111 | * @throws SerializationException
112 | */
113 | public function getDiscriminatedType(string $fqn): SerdeTypeClass
114 | {
115 | return $this->classDiscriminationInfo->getTypeByFullyQualifiedClassName($fqn);
116 | }
117 | }
--------------------------------------------------------------------------------
/test/WireMock/Client/MappingBuilderTest.php:
--------------------------------------------------------------------------------
1 | build()->thenReturn($mockRequestPattern);
20 | $this->_mockRequestPatternBuilder = $mockRequestPatternBuilder;
21 |
22 | $mockResponseDefinition = Phake::mock(ResponseDefinition::class);
23 |
24 | $mockResponseDefinitionBuilder = Phake::mock(ResponseDefinitionBuilder::class);
25 | Phake::when($mockResponseDefinitionBuilder)->build()->thenReturn($mockResponseDefinition);
26 | $this->_mockResponseDefinitionBuilder = $mockResponseDefinitionBuilder;
27 | }
28 |
29 | /**
30 | * @throws \Exception
31 | */
32 | public function testBuiltStubMappingHasRequestPatternAndResponseDefinition()
33 | {
34 | // given
35 | $mappingBuilder = new MappingBuilder($this->_mockRequestPatternBuilder);
36 | $mappingBuilder->willReturn($this->_mockResponseDefinitionBuilder);
37 |
38 | // when
39 | $stubMapping = $mappingBuilder->build();
40 |
41 | // then
42 | assertThat($stubMapping->getRequest(), notNullValue());
43 | assertThat($stubMapping->getResponse(), notNullValue());
44 | }
45 |
46 | /**
47 | * @throws \Exception
48 | */
49 | public function testMatchedRequestHeadersAreSetOnRequestPattern()
50 | {
51 | // given
52 | $mappingBuilder = new MappingBuilder($this->_mockRequestPatternBuilder);
53 | $mappingBuilder->willReturn($this->_mockResponseDefinitionBuilder);
54 | $headerName = 'aHeader';
55 | $valueMatchingStrategy = new ValueMatchingStrategy('equalTo', 'aValue');
56 |
57 | // when
58 | $mappingBuilder->withHeader($headerName, $valueMatchingStrategy)->build();
59 |
60 | // then
61 | Phake::verify($this->_mockRequestPatternBuilder)->withHeader($headerName, $valueMatchingStrategy);
62 | }
63 |
64 | /**
65 | * @throws \Exception
66 | */
67 | public function testMatchedRequestQueryParamsAreSetOnRequestPattern()
68 | {
69 | // given
70 | $mappingBuilder = new MappingBuilder($this->_mockRequestPatternBuilder);
71 | $mappingBuilder->willReturn($this->_mockResponseDefinitionBuilder);
72 | $paramName = 'aParam';
73 | $valueMatchingStrategy = new ValueMatchingStrategy('equalTo', 'aValue');
74 |
75 | // when
76 | $mappingBuilder->withQueryParam($paramName, $valueMatchingStrategy)->build();
77 |
78 | // then
79 | Phake::verify($this->_mockRequestPatternBuilder)->withQueryParam($paramName, $valueMatchingStrategy);
80 | }
81 |
82 | /**
83 | * @throws \Exception
84 | */
85 | public function testRequestBodyMatcherIsSetOnRequestPattern()
86 | {
87 | // given
88 | $mappingBuilder = new MappingBuilder($this->_mockRequestPatternBuilder);
89 | $mappingBuilder->willReturn($this->_mockResponseDefinitionBuilder);
90 |
91 | // when
92 | $valueMatchingStrategy = new ValueMatchingStrategy('matches', 'aValue');
93 | $mappingBuilder->withRequestBody($valueMatchingStrategy)
94 | ->build();
95 |
96 | // then
97 | Phake::verify($this->_mockRequestPatternBuilder)->withRequestBody($valueMatchingStrategy);
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/WireMock/Client/DateTimeMatchingStrategy.php:
--------------------------------------------------------------------------------
1 | expectedOffset = new DateTimeMatchExpectedOffset($amount, $unit);
51 | return $this;
52 | }
53 |
54 | /**
55 | * @param string $format
56 | * @return $this
57 | */
58 | public function actualFormat($format)
59 | {
60 | $this->actualFormat = $format;
61 | return $this;
62 | }
63 |
64 | /**
65 | * @param string $truncationType One of the truncation type constants on DateTimeMatchingStrategy
66 | * @return $this
67 | */
68 | public function truncateExpected($truncationType)
69 | {
70 | $this->truncateExpected = $truncationType;
71 | return $this;
72 | }
73 |
74 | /**
75 | * @param string $truncationType One of the truncation type constants on DateTimeMatchingStrategy
76 | * @return $this
77 | */
78 | public function truncateActual($truncationType)
79 | {
80 | $this->truncateActual = $truncationType;
81 | return $this;
82 | }
83 |
84 | /**
85 | * @return DateTimeMatchExpectedOffset|null
86 | */
87 | public function getExpectedOffset(): ?DateTimeMatchExpectedOffset
88 | {
89 | return $this->expectedOffset;
90 | }
91 |
92 | /**
93 | * @return string|null
94 | */
95 | public function getActualFormat(): ?string
96 | {
97 | return $this->actualFormat;
98 | }
99 |
100 | /**
101 | * @return string|null
102 | */
103 | public function getTruncateActual(): ?string
104 | {
105 | return $this->truncateActual;
106 | }
107 |
108 | /**
109 | * @return string|null
110 | */
111 | public function getTruncateExpected(): ?string
112 | {
113 | return $this->truncateExpected;
114 | }
115 |
116 | public static function before($dateTimeSpec)
117 | {
118 | return new self("before", $dateTimeSpec);
119 | }
120 |
121 | public static function equalToDateTime($dateTimeSpec)
122 | {
123 | return new self("equalToDateTime", $dateTimeSpec);
124 | }
125 |
126 | public static function after($dateTimeSpec)
127 | {
128 | return new self("after", $dateTimeSpec);
129 | }
130 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/Type/SerdeTypeUnion.php:
--------------------------------------------------------------------------------
1 | primitiveSerdeTypes = $primitiveSerdeTypes;
22 | $this->classOrArraySerdeType = $classOrArraySerdeType;
23 | }
24 |
25 | static function setSubtypes(SerdeTypeUnion $serdeType, array $primitiveSerdeTypes, $classOrArraySerdeType)
26 | {
27 | $serdeType->primitiveSerdeTypes = $primitiveSerdeTypes;
28 | $serdeType->classOrArraySerdeType = $classOrArraySerdeType;
29 | }
30 |
31 | function displayName(): string
32 | {
33 | $types = $this->primitiveSerdeTypes;
34 | if ($this->classOrArraySerdeType !== null) {
35 | $types[] = $this->classOrArraySerdeType;
36 | }
37 | $typeDisplayNames = array_map(function($t) { return '('.$t->displayName().')'; }, $types);
38 | return join('|', $typeDisplayNames);
39 | }
40 |
41 | function canDenormalize($data): bool
42 | {
43 | if ($this->classOrArraySerdeType !== null && $this->classOrArraySerdeType->canDenormalize($data)) {
44 | return true;
45 | }
46 | foreach ($this->primitiveSerdeTypes as $serdeType) {
47 | if ($serdeType->canDenormalize($data)) {
48 | return true;
49 | }
50 | }
51 | return false;
52 | }
53 |
54 | /**
55 | * @throws ReflectionException
56 | * @throws SerializationException
57 | */
58 | function denormalize(&$data, array $path)
59 | {
60 | if ($this->classOrArraySerdeType !== null && $this->classOrArraySerdeType->canDenormalize($data)) {
61 | return $this->classOrArraySerdeType->denormalize($data, $path);
62 | }
63 |
64 | foreach ($this->primitiveSerdeTypes as $serdeType) {
65 | if ($serdeType->canDenormalize($data)) {
66 | return $serdeType->denormalize($data, $path);
67 | }
68 | }
69 |
70 | $dataType = gettype($data);
71 | $targetType = $this->displayName();
72 | throw new SerializationException("Cannot denormalize data of type $dataType to $targetType");
73 | }
74 |
75 | /**
76 | * @return bool Whether the union represents either a nullable class type (and nothing more)
77 | */
78 | function isNullableClass(): bool
79 | {
80 | return $this->classOrArraySerdeType instanceof SerdeTypeClass &&
81 | count($this->primitiveSerdeTypes) === 1 &&
82 | $this->primitiveSerdeTypes[0] instanceof SerdeTypeNull;
83 | }
84 |
85 | /**
86 | * @return bool Whether the union represents either a nullable class type (and nothing more)
87 | */
88 | function isNullableArray(): bool
89 | {
90 | return $this->classOrArraySerdeType instanceof SerdeTypeArray &&
91 | count($this->primitiveSerdeTypes) === 1 &&
92 | $this->primitiveSerdeTypes[0] instanceof SerdeTypeNull;
93 | }
94 |
95 | /**
96 | * @throws SerializationException
97 | */
98 | function getClassTypeOrThrow(): SerdeTypeClass
99 | {
100 | if (!($this->classOrArraySerdeType instanceof SerdeTypeClass)) {
101 | throw new SerializationException('Expected a SerdeTypeClass but was ' . get_class($this->classOrArraySerdeType));
102 | }
103 | return $this->classOrArraySerdeType;
104 | }
105 | }
--------------------------------------------------------------------------------
/src/WireMock/Recording/RecordSpec.php:
--------------------------------------------------------------------------------
1 | targetBaseUrl = $targetBaseUrl;
56 | $this->filters = $filters;
57 | $this->captureHeaders = $captureHeaders;
58 | $this->extractBodyCriteria = $extractBodyCriteria;
59 | $this->persist = $persist;
60 | $this->repeatsAsScenarios = $repeatsAsScenarios;
61 | $this->transformers = $transformers;
62 | $this->transformerParameters = $transformerParameters;
63 | $this->requestBodyPattern = $requestBodyPattern;
64 | $this->outputFormat = $outputFormat;
65 | }
66 |
67 | /**
68 | * @return string
69 | */
70 | public function getTargetBaseUrl(): ?string
71 | {
72 | return $this->targetBaseUrl;
73 | }
74 |
75 | /**
76 | * @return ProxiedServeEventFilters|null
77 | */
78 | public function getFilters(): ?ProxiedServeEventFilters
79 | {
80 | return $this->filters;
81 | }
82 |
83 | /**
84 | * @return array|null
85 | */
86 | public function getCaptureHeaders(): ?array
87 | {
88 | return $this->captureHeaders;
89 | }
90 |
91 | /**
92 | * @return array|null
93 | */
94 | public function getExtractBodyCriteria(): ?array
95 | {
96 | return $this->extractBodyCriteria;
97 | }
98 |
99 | /**
100 | * @return bool
101 | */
102 | public function isPersist(): bool
103 | {
104 | return $this->persist;
105 | }
106 |
107 | /**
108 | * @return bool
109 | */
110 | public function isRepeatsAsScenarios(): bool
111 | {
112 | return $this->repeatsAsScenarios;
113 | }
114 |
115 | /**
116 | * @return string[]|null
117 | */
118 | public function getTransformers(): ?array
119 | {
120 | return $this->transformers;
121 | }
122 |
123 | /**
124 | * @return array|null
125 | */
126 | public function getTransformerParameters(): ?array
127 | {
128 | return $this->transformerParameters;
129 | }
130 |
131 | /**
132 | * @return array
133 | */
134 | public function getRequestBodyPattern(): ?array
135 | {
136 | return $this->requestBodyPattern;
137 | }
138 |
139 | /**
140 | * @return string
141 | */
142 | public function getOutputFormat(): ?string
143 | {
144 | return $this->outputFormat;
145 | }
146 | }
--------------------------------------------------------------------------------
/src/WireMock/Serde/Serializer.php:
--------------------------------------------------------------------------------
1 | serdeTypeLookup = $serdeTypeLookup;
20 | }
21 |
22 | /**
23 | * Serializes data object into JSON
24 | *
25 | * @param mixed $object object to serialize
26 | * @return string JSON serialization of object
27 | * @throws ReflectionException|SerializationException
28 | */
29 | public function serialize($object): string
30 | {
31 | $normalizedArray = $this->normalize($object, true);
32 | return json_encode($normalizedArray, JSON_UNESCAPED_SLASHES);
33 | }
34 |
35 | /**
36 | * @param mixed $object object to normalize
37 | * @param bool $isRoot whether this is the root object being normalized
38 | * @param ?SerdeType $serdeType the SerdeType of the class property being normalized (if applicable)
39 | * @return mixed An associative array or a primitive type
40 | * @throws ReflectionException
41 | * @throws SerializationException
42 | */
43 | public function normalize($object, bool $isRoot = false, $serdeType = null)
44 | {
45 | if (is_object($object)) {
46 | $type = get_class($object);
47 | if ($isRoot === true && $this->serdeTypeLookup->isRootType($type) === false) {
48 | fwrite(STDERR, "Warning: serializing from $type, but this is not a root type\n");
49 | }
50 | /** @var ?SerdeTypeClass $serdeType */
51 | $serdeType = $this->serdeTypeLookup->getSerdeTypeIfExits($type);
52 | if ($serdeType) {
53 | $result = $serdeType->normalize($object, $this);
54 | } else {
55 | // There's no SerdeType for this class, so we just return it as is, and let json_decode deal with it
56 | // This allows users to supply objects of unregistered types, perhaps as values within an untyped array,
57 | // and have them serialized (in a way they can control with JsonSerializable)
58 | return $object;
59 | }
60 | } elseif (is_array($object)) {
61 | $result = array_map(
62 | function($value) { return $this->normalize($value); },
63 | $object
64 | );
65 |
66 | if ($serdeType instanceof SerdeTypeAssocArray && empty($object)) {
67 | // We want empty associative arrays to be serialize as "{}" rather than "[]", so we use an empty stdClass
68 | // object rather than an empty PHP array as the normalized value
69 | $result = new stdClass();
70 | }
71 | } else {
72 | $result = $object;
73 | }
74 |
75 | return $result;
76 | }
77 |
78 | /**
79 | * Deserializes JSON into data object of the given type
80 | *
81 | * @param string $json
82 | * @param string $type
83 | *
84 | * @return mixed
85 | * @throws SerializationException
86 | */
87 | public function deserialize(string $json, string $type)
88 | {
89 | $data = json_decode($json, true);
90 | return $this->denormalize($data, $type, true);
91 | }
92 |
93 | /**
94 | * @throws SerializationException
95 | */
96 | public function denormalize(&$data, string $type, bool $isRoot = false)
97 | {
98 | $serdeType = $this->serdeTypeLookup->getSerdeType($type);
99 | if ($isRoot === true && $this->serdeTypeLookup->isRootType($type) === false) {
100 | fwrite(STDERR, "Warning: deserializing to $type, but this is not a root type\n");
101 | }
102 | return $serdeType->denormalize($data, []);
103 | }
104 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/ValueMatchingStrategy.php:
--------------------------------------------------------------------------------
1 | ValueMatchingStrategy::class,
23 | 'binaryEqualTo' => ValueMatchingStrategy::class,
24 | 'contains' => ValueMatchingStrategy::class,
25 | 'doesNotContain' => ValueMatchingStrategy::class,
26 | 'matches' => ValueMatchingStrategy::class,
27 | 'doesNotMatch' => ValueMatchingStrategy::class,
28 |
29 | 'before' => DateTimeMatchingStrategy::class,
30 | 'equalToDateTime' => DateTimeMatchingStrategy::class,
31 | 'after' => DateTimeMatchingStrategy::class,
32 |
33 | 'equalTo' => EqualToMatchingStrategy::class,
34 |
35 | 'matchesXPath' => XPathValueMatchingStrategy::class,
36 |
37 | 'equalToXml' => EqualToXmlMatchingStrategy::class,
38 |
39 | 'matchesJsonPath' => JsonPathValueMatchingStrategy::class,
40 |
41 | 'equalToJson' => JsonValueMatchingStrategy::class,
42 |
43 | 'and' => LogicalOperatorMatchingStrategy::class,
44 | 'or' => LogicalOperatorMatchingStrategy::class,
45 | ];
46 | /** @noinspection PhpUnusedPrivateMethodInspection */
47 | private static function matchingValueNames(): array { return array_keys(self::$subclassByMatchingType); }
48 |
49 | /** @var string */
50 | protected $matchingType;
51 | /**
52 | * @var string|boolean|ValueMatchingStrategy[]
53 | * @serde-named-by matchingType
54 | * @serde-possible-names matchingValueNames
55 | */
56 | protected $matchingValue;
57 |
58 | public function __construct($matchingType, $matchingValue)
59 | {
60 | $this->matchingType = $matchingType;
61 | $this->matchingValue = $matchingValue;
62 | }
63 |
64 | /**
65 | * @return string
66 | */
67 | public function getMatchingType(): string
68 | {
69 | return $this->matchingType;
70 | }
71 |
72 | /**
73 | * @return bool|string|ValueMatchingStrategy[]
74 | */
75 | public function getMatchingValue()
76 | {
77 | return $this->matchingValue;
78 | }
79 |
80 | public function and(ValueMatchingStrategy $other)
81 | {
82 | return LogicalOperatorMatchingStrategy::andAll($this, $other);
83 | }
84 |
85 | public function or(ValueMatchingStrategy $other)
86 | {
87 | return LogicalOperatorMatchingStrategy::orAll($this, $other);
88 | }
89 |
90 | /** @noinspection PhpUnusedPrivateMethodInspection */
91 | private static function getDiscriminatorMapping(): ClassDiscriminator
92 | {
93 | return new class(self::$subclassByMatchingType) implements ClassDiscriminator {
94 | private $subclassByMatchingType;
95 | public function __construct($subclassByMatchingType)
96 | {
97 | $this->subclassByMatchingType = $subclassByMatchingType;
98 | }
99 |
100 | function getDiscriminatedType($data): string
101 | {
102 | foreach ($data as $key => $value) {
103 | if (isset($this->subclassByMatchingType[$key])) {
104 | return $this->subclassByMatchingType[$key];
105 | }
106 | }
107 | throw new SerializationException("Cannot discriminate subclass of ValueMatchingStrategy");
108 | }
109 | };
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/WireMock/Stubbing/StubMapping.php:
--------------------------------------------------------------------------------
1 | id = $id;
59 | $this->name = $name;
60 | $this->request = $request;
61 | $this->response = $response;
62 | $this->priority = $priority;
63 | $this->metadata = $metadata;
64 | $this->persistent = $persistent;
65 | $this->postServeActions = $postServeActions;
66 |
67 | if ($scenarioMapping) {
68 | $this->scenarioName = $scenarioMapping->getScenarioName();
69 | $this->requiredScenarioState = $scenarioMapping->getRequiredScenarioState();
70 | $this->newScenarioState = $scenarioMapping->getNewScenarioState();
71 | }
72 | }
73 |
74 | /**
75 | * @return string
76 | */
77 | public function getId()
78 | {
79 | return $this->id;
80 | }
81 |
82 | /**
83 | * @param string $id
84 | */
85 | public function setId($id)
86 | {
87 | $this->id = $id;
88 | }
89 |
90 | /**
91 | * @return string|null
92 | */
93 | public function getName()
94 | {
95 | return $this->name;
96 | }
97 |
98 | /**
99 | * @return RequestPattern
100 | */
101 | public function getRequest()
102 | {
103 | return $this->request;
104 | }
105 |
106 | /**
107 | * @return ResponseDefinition
108 | */
109 | public function getResponse()
110 | {
111 | return $this->response;
112 | }
113 |
114 | /**
115 | * @return int
116 | */
117 | public function getPriority()
118 | {
119 | return $this->priority;
120 | }
121 |
122 | /**
123 | * @return array
124 | */
125 | public function getMetadata()
126 | {
127 | return $this->metadata;
128 | }
129 |
130 | /**
131 | * @return boolean|null
132 | */
133 | public function isPersistent()
134 | {
135 | return $this->persistent;
136 | }
137 |
138 | /**
139 | * @return string
140 | */
141 | public function getScenarioName()
142 | {
143 | return $this->scenarioName;
144 | }
145 |
146 | /**
147 | * @return string
148 | */
149 | public function getRequiredScenarioState()
150 | {
151 | return $this->requiredScenarioState;
152 | }
153 |
154 | /**
155 | * @return string
156 | */
157 | public function getNewScenarioState()
158 | {
159 | return $this->newScenarioState;
160 | }
161 |
162 | /**
163 | * @return PostServeAction[]|null
164 | */
165 | public function getPostServeActions(): ?array
166 | {
167 | return $this->postServeActions;
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/src/WireMock/Matching/RequestPattern.php:
--------------------------------------------------------------------------------
1 | |null */
19 | private $headers;
20 | /** @var array|null */
21 | private $cookies;
22 | /** @var array|null */
23 | private $queryParameters;
24 | /** @var ValueMatchingStrategy[]|null */
25 | private $bodyPatterns;
26 | /** @var MultipartValuePattern[]|null */
27 | private $multipartPatterns;
28 | /** @var ?BasicCredentials */
29 | private $basicAuthCredentials;
30 | /** @var ?CustomMatcherDefinition */
31 | private $customMatcher;
32 | /** @var ?ValueMatchingStrategy */
33 | private $host;
34 |
35 | /**
36 | * @param string $method
37 | * @param UrlMatchingStrategy $urlMatchingStrategy
38 | * @param array|null $headers
39 | * @param array|null $cookies
40 | * @param ValueMatchingStrategy[]|null $bodyPatterns
41 | * @param ValueMatchingStrategy[] $multipartPatterns
42 | * @param array|null $queryParameters
43 | * @param BasicCredentials $basicCredentials
44 | * @param CustomMatcherDefinition $customMatcherDefinition
45 | * @param ValueMatchingStrategy $hostPattern
46 | */
47 | public function __construct(
48 | $method,
49 | $urlMatchingStrategy,
50 | $headers = null,
51 | $cookies = null,
52 | $bodyPatterns = null,
53 | $multipartPatterns = null,
54 | $queryParameters = null,
55 | $basicCredentials = null,
56 | $customMatcherDefinition = null,
57 | $hostPattern = null
58 | ) {
59 | $this->method = $method;
60 | $this->urlMatchingStrategy = $urlMatchingStrategy;
61 | $this->headers = $headers;
62 | $this->cookies = $cookies;
63 | $this->bodyPatterns = $bodyPatterns;
64 | $this->queryParameters = $queryParameters;
65 | $this->basicAuthCredentials = $basicCredentials;
66 | $this->multipartPatterns = $multipartPatterns;
67 | $this->customMatcher = $customMatcherDefinition;
68 | $this->host = $hostPattern;
69 | }
70 |
71 | /**
72 | * @return string
73 | */
74 | public function getMethod()
75 | {
76 | return $this->method;
77 | }
78 |
79 | /**
80 | * @return UrlMatchingStrategy
81 | */
82 | public function getUrlMatchingStrategy()
83 | {
84 | return $this->urlMatchingStrategy;
85 | }
86 |
87 | /**
88 | * @return array
89 | */
90 | public function getHeaders()
91 | {
92 | return $this->headers;
93 | }
94 |
95 | /**
96 | * @return array
97 | */
98 | public function getCookies()
99 | {
100 | return $this->cookies;
101 | }
102 |
103 | /**
104 | * @return array
105 | */
106 | public function getQueryParameters()
107 | {
108 | return $this->queryParameters;
109 | }
110 |
111 | /**
112 | * @return ValueMatchingStrategy[]
113 | */
114 | public function getBodyPatterns()
115 | {
116 | return $this->bodyPatterns;
117 | }
118 |
119 | /**
120 | * @return ValueMatchingStrategy[]
121 | */
122 | public function getMultipartPatterns()
123 | {
124 | return $this->multipartPatterns;
125 | }
126 |
127 | /**
128 | * @return BasicCredentials
129 | */
130 | public function getBasicAuthCredentials()
131 | {
132 | return $this->basicAuthCredentials;
133 | }
134 |
135 | /**
136 | * @return CustomMatcherDefinition
137 | */
138 | public function getCustomMatcher()
139 | {
140 | return $this->customMatcher;
141 | }
142 |
143 | /**
144 | * @return ValueMatchingStrategy|null
145 | */
146 | public function getHost()
147 | {
148 | return $this->host;
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/test/WireMock/Client/RequestPatternBuilderTest.php:
--------------------------------------------------------------------------------
1 | build();
20 |
21 | // then
22 | assertThat($requestPattern->getMethod(), is($method));
23 | assertThat($requestPattern->getUrlMatchingStrategy(), is($matchingStrategy));
24 | }
25 |
26 | public function testHeaderWithValueMatchingStrategyIsInArrayIfSpecified()
27 | {
28 | // given
29 | $requestPatternBuilder = new RequestPatternBuilder('GET', WireMock::urlEqualTo('/some/url'));
30 | $matchingStrategy = WireMock::equalTo('something');
31 |
32 | // when
33 | $requestPatternBuilder->withHeader('Some-Header', $matchingStrategy);
34 | $requestPattern = $requestPatternBuilder->build();
35 |
36 | // then
37 | assertThat($requestPattern->getHeaders(), hasEntry('Some-Header', $matchingStrategy));
38 | }
39 |
40 | public function testHeaderAbsenceIsInArrayIfSpecified()
41 | {
42 | // given
43 | $requestPatternBuilder = new RequestPatternBuilder('GET', WireMock::urlEqualTo('/some/url'));
44 | $matchingStrategy = new ValueMatchingStrategy('absent', true);
45 |
46 | // when
47 | $requestPatternBuilder->withoutHeader('Some-Header');
48 | $requestPattern = $requestPatternBuilder->build();
49 |
50 | // then
51 | assertThat($requestPattern->getHeaders(), hasEntry('Some-Header', $matchingStrategy));
52 | }
53 |
54 | public function testCookieWithValueMatchingStrategyIsInArrayIfSpecified()
55 | {
56 | // given
57 | $requestPatternBuilder = new RequestPatternBuilder('GET', WireMock::urlEqualTo('/some/url'));
58 | $matchingStrategy = WireMock::equalTo('something');
59 |
60 | // when
61 | $requestPatternBuilder->withCookie('aCookie', $matchingStrategy);
62 | $requestPattern = $requestPatternBuilder->build();
63 |
64 | // then
65 | assertThat($requestPattern->getCookies(), hasEntry('aCookie', $matchingStrategy));
66 | }
67 |
68 | public function testRequestBodyPatternsAreInArrayIfSpecified()
69 | {
70 | // given
71 | $requestPatternBuilder = new RequestPatternBuilder('GET', WireMock::urlEqualTo('/some/url'));
72 | $matchingStrategy = new ValueMatchingStrategy('equalTo', 'aValue');
73 |
74 | // when
75 | $requestPatternBuilder->withRequestBody($matchingStrategy);
76 | $requestPattern = $requestPatternBuilder->build();
77 |
78 | // then
79 | assertThat($requestPattern->getBodyPatterns(), hasItem($matchingStrategy));
80 | }
81 |
82 | public function testBasicAuthIsInArrayIfSpecified()
83 | {
84 | // given
85 | $requestPatternBuilder = new RequestPatternBuilder('GET', WireMock::urlEqualTo('/some/url'));
86 |
87 | // when
88 | $requestPatternBuilder->withBasicAuth('uname', 'pword');
89 | $requestPattern = $requestPatternBuilder->build();
90 |
91 | // then
92 | assertThat($requestPattern->getBasicAuthCredentials(), equalTo(
93 | new BasicCredentials('uname', 'pword')));
94 | }
95 |
96 | public function testBuilderCanBeCreatedWithCustomMatcherNameAndParams()
97 | {
98 | // when
99 | $customMatcherName = 'custom-matcher';
100 | $params = array('param' => 'val');
101 | $builder = new RequestPatternBuilder($customMatcherName, $params);
102 | $pattern = $builder->build();
103 |
104 | // then
105 | assertThat($pattern->getMethod(), nullValue());
106 | assertThat($pattern->getUrlMatchingStrategy(), nullValue());
107 | assertThat($pattern->getCustomMatcher(), equalTo(new CustomMatcherDefinition($customMatcherName, $params)));
108 | }
109 |
110 | public function testCustomMatcherDefinitionIsInArrayIfSpecified()
111 | {
112 | // given
113 | $builder = new RequestPatternBuilder('GET', WireMock::urlEqualTo('/some/url'));
114 | $customMatcherName = 'custom-matcher';
115 | $params = array('param' => 'val');
116 |
117 | // when
118 | $builder->withCustomMatcher($customMatcherName, $params);
119 | $pattern = $builder->build();
120 |
121 | // then
122 | assertThat($pattern->getCustomMatcher(), equalTo(new CustomMatcherDefinition($customMatcherName, $params)));
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/test/WireMock/Integration/MappingsIntegrationTest.php:
--------------------------------------------------------------------------------
1 | listAllStubMappings();
13 |
14 | // then
15 | assertThat($mappings->getMappings(), emptyArray());
16 | }
17 |
18 | public function testMappingListContainsStubsPreviouslyCreated()
19 | {
20 | // given
21 | $mapping = self::$_wireMock->stubFor(WireMock::any(WireMock::anyUrl())->willReturn(WireMock::aResponse()));
22 |
23 | // when
24 | $mappings = self::$_wireMock->listAllStubMappings();
25 |
26 | // then
27 | assertThat($mappings->getMappings(), hasItemInArray($mapping));
28 | }
29 |
30 | public function testMappingListCanBeLimitedToMostRecent()
31 | {
32 | // given
33 | self::$_wireMock->stubFor(WireMock::any(WireMock::urlEqualTo('/one'))
34 | ->willReturn(WireMock::aResponse()));
35 | $mapping = self::$_wireMock->stubFor(WireMock::any(WireMock::urlEqualTo('/two'))
36 | ->willReturn(WireMock::aResponse()));
37 |
38 | // when
39 | $mappings = self::$_wireMock->listAllStubMappings(1);
40 |
41 | // then
42 | assertThat($mappings->getMappings(), allOf(hasItemInArray($mapping), arrayWithSize(1)));
43 | }
44 |
45 | public function testMappingListCanBeOffsetToRetrieveOlderStubs()
46 | {
47 | // given
48 | $mapping = self::$_wireMock->stubFor(WireMock::any(WireMock::urlEqualTo('/one'))
49 | ->willReturn(WireMock::aResponse()));
50 | self::$_wireMock->stubFor(WireMock::any(WireMock::urlEqualTo('/two'))
51 | ->willReturn(WireMock::aResponse()));
52 |
53 | // when
54 | $mappings = self::$_wireMock->listAllStubMappings(1, 1);
55 |
56 | // then
57 | assertThat($mappings->getMappings(), allOf(hasItemInArray($mapping), arrayWithSize(1)));
58 | }
59 |
60 | public function testGettingSingleMappingRetrievesStubById()
61 | {
62 | // given
63 | $mapping = self::$_wireMock->stubFor(WireMock::any(WireMock::urlEqualTo('/one'))
64 | ->willReturn(WireMock::aResponse()));
65 |
66 | // when
67 | $returnedMapping = self::$_wireMock->getSingleStubMapping($mapping->getId());
68 |
69 | // then
70 | assertThat($returnedMapping, equalTo($mapping));
71 | }
72 |
73 | public function testStubsCanBeFoundByMetadata()
74 | {
75 | // given
76 | self::$_wireMock->stubFor(WireMock::any(WireMock::urlEqualTo('/one'))
77 | ->withMetadata(array('customId' => 123))
78 | ->willReturn(WireMock::aResponse()));
79 |
80 | // when
81 | $mappingsResult = self::$_wireMock->findStubsByMetadata(
82 | WireMock::matchingJsonPath('$.customId', WireMock::equalTo('123'))
83 | );
84 |
85 | // then
86 | assertThat($mappingsResult->getMappings(), arrayWithSize(1));
87 | $mappings = $mappingsResult->getMappings();
88 | assertThat($mappings[0]->getMetadata(), equalTo(array('customId' => 123)));
89 | }
90 |
91 | public function testStubsNotMatchingMetadataAreNotFound()
92 | {
93 | // given
94 | self::$_wireMock->stubFor(WireMock::any(WireMock::urlEqualTo('/one'))
95 | ->withMetadata(array('customId' => 123))
96 | ->willReturn(WireMock::aResponse()));
97 |
98 | // when
99 | $mappingsResult = self::$_wireMock->findStubsByMetadata(
100 | WireMock::matchingJsonPath('$.customId', WireMock::equalTo('a different value'))
101 | );
102 |
103 | // then
104 | assertThat($mappingsResult->getMappings(), arrayWithSize(0));
105 | }
106 |
107 | public function testStubsCanBeRemovedByMetadata()
108 | {
109 | // given
110 | self::$_wireMock->stubFor(WireMock::any(WireMock::urlEqualTo('/one'))
111 | ->withMetadata(array('customId' => 123))
112 | ->willReturn(WireMock::aResponse()));
113 |
114 | // when
115 | self::$_wireMock->removeStubsByMetadata(
116 | WireMock::matchingJsonPath('$.customId', WireMock::equalTo('123'))
117 | );
118 |
119 | // then
120 | assertThat(self::$_wireMock->listAllStubMappings()->getMappings(), arrayWithSize(0));
121 | }
122 |
123 | public function testStubsNotMatchingMetadataAreNotRemoved()
124 | {
125 | // given
126 | self::$_wireMock->stubFor(WireMock::any(WireMock::urlEqualTo('/one'))
127 | ->withMetadata(array('customId' => 123))
128 | ->willReturn(WireMock::aResponse()));
129 |
130 | // when
131 | self::$_wireMock->removeStubsByMetadata(
132 | WireMock::matchingJsonPath('$.customId', WireMock::equalTo('a different value'))
133 | );
134 |
135 | // then
136 | assertThat(self::$_wireMock->listAllStubMappings()->getMappings(), arrayWithSize(1));
137 | }
138 | }
--------------------------------------------------------------------------------
/src/WireMock/Client/RequestPatternBuilder.php:
--------------------------------------------------------------------------------
1 | |null */
14 | private $headers;
15 | /** @var array|null */
16 | private $cookies;
17 | /** @var array|null */
18 | private $queryParameters;
19 | /** @var ValueMatchingStrategy[]|null */
20 | private $bodyPatterns;
21 | /** @var MultipartValuePattern[]|null */
22 | private $multipartPatterns;
23 | /** @var BasicCredentials */
24 | private $basicCredentials;
25 | /** @var CustomMatcherDefinition */
26 | private $customMatcherDefinition;
27 | /** @var ValueMatchingStrategy[] */
28 | private $hostPattern;
29 |
30 | /**
31 | * @param string $methodOrCustomMatcherName
32 | * @param UrlMatchingStrategy|array $urlMatchingStrategyOrCustomParams
33 | */
34 | public function __construct($methodOrCustomMatcherName, $urlMatchingStrategyOrCustomParams)
35 | {
36 | if ($urlMatchingStrategyOrCustomParams instanceof UrlMatchingStrategy) {
37 | $this->method = $methodOrCustomMatcherName;
38 | $this->urlMatchingStrategy = $urlMatchingStrategyOrCustomParams;
39 | } else {
40 | $this->customMatcherDefinition =
41 | new CustomMatcherDefinition($methodOrCustomMatcherName, $urlMatchingStrategyOrCustomParams);
42 | }
43 | }
44 |
45 | /**
46 | * @param string $headerName
47 | * @param ValueMatchingStrategy $valueMatchingStrategy
48 | * @return RequestPatternBuilder
49 | */
50 | public function withHeader($headerName, ValueMatchingStrategy $valueMatchingStrategy)
51 | {
52 | $this->headers[$headerName] = $valueMatchingStrategy;
53 | return $this;
54 | }
55 |
56 | /**
57 | * @param string $cookieName
58 | * @param ValueMatchingStrategy $valueMatchingStrategy
59 | * @return RequestPatternBuilder
60 | */
61 | public function withCookie($cookieName, ValueMatchingStrategy $valueMatchingStrategy)
62 | {
63 | $this->cookies[$cookieName] = $valueMatchingStrategy;
64 | return $this;
65 | }
66 |
67 | /**
68 | * @param string $headerName
69 | * @return RequestPatternBuilder
70 | */
71 | public function withoutHeader($headerName)
72 | {
73 | $this->withHeader($headerName, new ValueMatchingStrategy('absent', true));
74 | return $this;
75 | }
76 |
77 | /**
78 | * @param string $name
79 | * @param ValueMatchingStrategy $valueMatchingStrategy
80 | * @return RequestPatternBuilder
81 | */
82 | public function withQueryParam($name, ValueMatchingStrategy $valueMatchingStrategy)
83 | {
84 | $this->queryParameters[$name] = $valueMatchingStrategy;
85 | return $this;
86 | }
87 |
88 | /**
89 | * @param ValueMatchingStrategy $valueMatchingStrategy
90 | * @return RequestPatternBuilder
91 | */
92 | public function withRequestBody(ValueMatchingStrategy $valueMatchingStrategy)
93 | {
94 | $this->bodyPatterns[] = $valueMatchingStrategy;
95 | return $this;
96 | }
97 |
98 | /**
99 | * @param MultipartValuePattern $multipart
100 | * @return $this
101 | */
102 | public function withMultipartRequestBody($multipart)
103 | {
104 | $this->multipartPatterns[] = $multipart;
105 | return $this;
106 | }
107 |
108 | /**
109 | * @param string $username
110 | * @param string $password
111 | * @return RequestPatternBuilder
112 | */
113 | public function withBasicAuth($username, $password)
114 | {
115 | $this->basicCredentials = new BasicCredentials($username, $password);
116 | return $this;
117 | }
118 |
119 | /**
120 | * @param string $customMatcherName
121 | * @param array $customParams
122 | * @return RequestPatternBuilder
123 | */
124 | public function withCustomMatcher($customMatcherName, $customParams)
125 | {
126 | $this->customMatcherDefinition = new CustomMatcherDefinition($customMatcherName, $customParams);
127 | return $this;
128 | }
129 |
130 | /**
131 | * @param ValueMatchingStrategy $hostMatcher
132 | * @return $this
133 | */
134 | public function withHost($hostMatcher)
135 | {
136 | $this->hostPattern = $hostMatcher;
137 | return $this;
138 | }
139 |
140 | /**
141 | * @return RequestPattern
142 | */
143 | public function build()
144 | {
145 | return new RequestPattern(
146 | $this->method,
147 | $this->urlMatchingStrategy,
148 | $this->headers,
149 | $this->cookies,
150 | $this->bodyPatterns,
151 | $this->multipartPatterns,
152 | $this->queryParameters,
153 | $this->basicCredentials,
154 | $this->customMatcherDefinition,
155 | $this->hostPattern
156 | );
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | wiremock-php [](https://dl.circleci.com/status-badge/redirect/gh/rowanhill/wiremock-php/tree/master)
2 | ============
3 | **Stub and mock web services with the power of [WireMock](https://github.com/tomakehurst/wiremock) from PHP.**
4 |
5 | WireMock provides a JSON API for interacting with it; wiremock-php makes it easy to use that JSON API from PHP by
6 | wrapping it up in a fluent API very similar to the Java API provided by WireMock.
7 |
8 | Note that wiremock-php requires a standalone instance of WireMock to be run (which requires Java).
9 |
10 | Version numbers track those of WireMock itself, but may lag behind (i.e. if a WireMock release does not contain changes
11 | to the API, there may be no corresponding version of wiremock-php).
12 |
13 | Alternatives
14 | ------------
15 | Like the idea of stubbing & verifying HTTP requests, but don't like this library (maybe you don't want to install Java)?
16 | You might want to investigate the following:
17 | * [http-mock](https://github.com/InterNations/http-mock)
18 | * [mock-http-server](https://github.com/cepa/mock-http-server)
19 |
20 | Installation
21 | ------------
22 | It's easiest to install wiremock-php via Composer:
23 |
24 | ```bash
25 | php composer.phar require --dev wiremock-php/wiremock-php:2.35.3
26 | ```
27 |
28 | Usage
29 | -----
30 | ### API
31 | The API is based directly on WireMock's Java API, so see the [WireMock documentation](http://wiremock.org/) for general
32 | help with interacting with WireMock.
33 |
34 | ### Differences to Java API
35 | To provide a fluent interface, the WireMock Java API makes use of statically imported methods (which act upon a default
36 | static instance), but it's also possible to act directly upon a Java WireMock instance (using slightly differently
37 | named methods).
38 |
39 | Prior to version 5.6 (back when wiremock-php was created), PHP didn't support anything like Java's static import of
40 | methods. Instead, in wiremock-php some methods which are static in Java are instance methods. Those methods are:
41 |
42 | - `stubFor`, `editStub`, `importStubs`
43 | - `verify`
44 | - `get`, `post`, `put`, `delete`, `patch`, `head`, `options`, `trace`, `any`
45 | - all the various matcher methods
46 | - `getAllServeEvents`, `findAll`, `findUnmatchedRequests`, `findNearMissesFor`, `findNearMissesForAllUnmatched`
47 | - `listAllStubMappings`, `getSingleStubMapping`, `findStubsByMetadata`, `removeStubsByMetadata`
48 | - `saveAllMappings`
49 | - `reset`, `resetToDefault`
50 | - `resetAllRequests`, `removeServeEvent`, `removeServeEvents`, `removeEventsByStubMetadata`
51 | - `getAllScenarios`, `resetAllScenarios`, `resetScenario`, `setScenarioState`
52 | - `setGlobalFixedDelay`, `setGlobalRandomDelay`, `resetGlobalDelays`
53 | - `startRecording`, `getRecordingStatus`, `stopRecording`, `snapshotRecord`
54 | - `shutdownServer`
55 |
56 | Also, the Java API has methods (`ResponseDefinitionBuilder::withBody` and `WebhookDefinition::withBinaryBody`) that take
57 | a byte array. Byte arrays are less common in PHP, so instead, `withBodyData` methods are provided, which takes a string
58 | to be base64 encoded. To produce an appropriate string from an array of bytes, use [pack](http://php.net/pack).
59 |
60 | The date and time request matcher functions (`before`, `beforeNow`, `equalToDateTime`, `isNow`, `after`, `afterNow`) can
61 | be used with offsets (`expectedOffset($amount, $unit)`). In the Java API, the unit parameter is an enum; in wiremock-php
62 | these values are consts on `DateTimeMatchingStrategy`. Similarly, truncation types (for use with `truncateExpected` and
63 | `truncateActual`) are enums in the Java API, but are consts on `DateTimeMatchingStrategy` in wiremock-php.
64 |
65 | The `stubImport` method is static on `StubBuilder` in Java. In WireMock, to keep all the public static methods in one
66 | predictable place, this method is available as `WireMock::stubImport`.
67 |
68 | The request method constants are available on `WireMock\Http\RequestMethod`.
69 |
70 | In addition, wiremock-php adds the instance method `isAlive`. This polls the standalone WireMock instance until an OK
71 | response is received or a timeout is reached, allowing your PHP code to wait until WireMock is ready.
72 |
73 | ### Example
74 | A typical usage looks something like the following:
75 | ```php
76 | // Create an object to administer a WireMock instance. This is assumed to be at
77 | // localhost:8080 unless these values are overridden.
78 | $wireMock = WireMock::create(/* specify host, port here if needed */);
79 |
80 | // Assert that the standalone service is running (by waiting for it to respond
81 | // to a request within a timeout)
82 | assertThat($wireMock->isAlive(), is(true));
83 |
84 | // Stub out a request
85 | $wireMock->stubFor(WireMock::get(WireMock::urlEqualTo('/some/url'))
86 | ->willReturn(WireMock::aResponse()
87 | ->withHeader('Content-Type', 'text/plain')
88 | ->withBody('Hello world!')));
89 |
90 | // ... interact with the server ...
91 |
92 | // Verify a request
93 | $wireMock->verify(WireMock::postRequestedFor(WireMock::urlEqualTo('/verify/this'))
94 | ->withHeader('Content-Type', WireMock::equalTo('text/xml')));
95 | ```
96 |
97 | ### Verification PHPUnit integration
98 | If a verification fails a `VerificationException` is thrown. If PHPUnit is present on the include path, this will be a
99 | subclass of `PHPUnit_Framework_AssertionFailedError`, thus causing any containing PHPUnit test to fail; if PHPUnit is
100 | not present, `VerificationException` subclasses `Exception`.
101 |
--------------------------------------------------------------------------------