Skip to content

Commit afde8e5

Browse files
committed
Enhancement: Implement StrictClient
1 parent 6dcd595 commit afde8e5

6 files changed

+422
-0
lines changed

Diff for: spec/Exception/RequestMismatchExceptionSpec.php

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace spec\Http\Mock\Exception;
4+
5+
use Http\Mock\Exception\RequestMismatchException;
6+
use Http\Mock\Exception\UnexpectedRequestException;
7+
use Http\Mock\StrictClient;
8+
use PhpSpec\ObjectBehavior;
9+
use Psr\Http\Message\RequestInterface;
10+
11+
class RequestMismatchExceptionSpec extends ObjectBehavior
12+
{
13+
function it_is_initializable()
14+
{
15+
$this->shouldHaveType(RequestMismatchException::class);
16+
}
17+
18+
function it_is_runtime_exception()
19+
{
20+
$this->shouldHaveType(\RuntimeException::class);
21+
}
22+
23+
function it_can_be_created_from_matcher_exception()
24+
{
25+
$exception = new \Exception('Hmm');
26+
27+
$this->beConstructedThrough('fromMatcherException', [
28+
$exception,
29+
]);
30+
31+
$this->shouldHaveType(RequestMismatchException::class);
32+
$this->getMessage()->shouldReturn('Expected a different request to be sent.');
33+
$this->getPrevious()->shouldReturn($exception);
34+
}
35+
36+
function it_can_be_created_with_create()
37+
{
38+
$this->beConstructedThrough('create');
39+
40+
$this->shouldHaveType(RequestMismatchException::class);
41+
$this->getMessage()->shouldReturn('Expected a different request to be sent.');
42+
}
43+
}

Diff for: spec/Exception/UnexpectedRequestExceptionSpec.php

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace spec\Http\Mock\Exception;
4+
5+
use Http\Mock\Exception\UnexpectedRequestException;
6+
use PhpSpec\ObjectBehavior;
7+
use Psr\Http\Message\RequestInterface;
8+
9+
class UnexpectedRequestExceptionSpec extends ObjectBehavior
10+
{
11+
function it_is_initializable()
12+
{
13+
$this->shouldHaveType(UnexpectedRequestException::class);
14+
}
15+
16+
function it_is_runtime_exception()
17+
{
18+
$this->shouldHaveType(\RuntimeException::class);
19+
}
20+
21+
function it_can_be_created_from_request(RequestInterface $request)
22+
{
23+
$this->beConstructedThrough('fromRequest', [
24+
$request,
25+
]);
26+
27+
$this->shouldHaveType(UnexpectedRequestException::class);
28+
$this->getMessage()->shouldReturn('Did not expect request to be sent');
29+
$this->getRequest()->shouldReturn($request->getWrappedObject());
30+
}
31+
}

Diff for: spec/StrictClientSpec.php

+167
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
<?php
2+
3+
namespace spec\Http\Mock;
4+
5+
use Http\Client\HttpAsyncClient;
6+
use Http\Client\HttpClient;
7+
use Http\Message\RequestMatcher;
8+
use Http\Message\ResponseFactory;
9+
use Http\Mock\Client;
10+
use Http\Mock\Exception\RequestMismatchException;
11+
use Http\Mock\Exception\UnexpectedRequestException;
12+
use Http\Mock\StrictClient;
13+
use PhpSpec\Matcher\MatcherInterface;
14+
use Psr\Http\Message\RequestInterface;
15+
use Psr\Http\Message\ResponseInterface;
16+
use PhpSpec\ObjectBehavior;
17+
18+
/**
19+
* @mixin StrictClient
20+
*/
21+
class StrictClientSpec extends ObjectBehavior
22+
{
23+
function it_is_initializable()
24+
{
25+
$this->shouldHaveType(StrictClient::class);
26+
}
27+
28+
function it_is_an_http_client()
29+
{
30+
$this->shouldImplement(HttpClient::class);
31+
}
32+
33+
function it_is_an_async_http_client()
34+
{
35+
$this->shouldImplement(HttpAsyncClient::class);
36+
}
37+
38+
function it_throws_when_no_matchers_have_been_configured(RequestInterface $request)
39+
{
40+
$this
41+
->shouldThrow(UnexpectedRequestException::fromRequest($request->getWrappedObject()))
42+
->duringSendRequest($request);
43+
}
44+
45+
function it_throws_when_next_request_matcher_throws_exception(
46+
RequestMatcher $matcher,
47+
RequestInterface $request,
48+
ResponseInterface $response
49+
) {
50+
$exception = new \Exception('Failed asserting that request method is "POST", got "GET" instead.');
51+
52+
$matcher->matches($request)->willThrow($exception);
53+
54+
$this->on($matcher, $response);
55+
56+
$this
57+
->shouldThrow(RequestMismatchException::fromMatcherException($exception))
58+
->duringSendRequest($request);
59+
}
60+
61+
function it_throws_when_next_request_matcher_does_not_match_request(
62+
RequestMatcher $matcher,
63+
RequestInterface $request,
64+
ResponseInterface $response
65+
) {
66+
$matcher->matches($request)->willReturn(false);
67+
68+
$this->on($matcher, $response);
69+
70+
$this
71+
->shouldThrow(RequestMismatchException::create())
72+
->duringSendRequest($request);
73+
}
74+
75+
function it_throws_configured_exception_when_next_request_matcher_matches_request(
76+
RequestMatcher $matcher,
77+
RequestInterface $request,
78+
ResponseInterface $response
79+
) {
80+
$exception = new \Exception('Sending the request failed because of a network error');
81+
82+
$matcher->matches($request)->willReturn(true);
83+
84+
$this->on($matcher, $exception);
85+
86+
$this
87+
->shouldThrow($exception)
88+
->duringSendRequest($request);
89+
}
90+
91+
function it_returns_configured_request_when_next_request_matcher_matches_request(
92+
RequestMatcher $matcher,
93+
RequestInterface $request,
94+
ResponseInterface $response
95+
) {
96+
$matcher->matches($request)->willReturn(true);
97+
98+
$this->on($matcher, $response);
99+
100+
$this->sendRequest($request)->shouldReturn($response);
101+
}
102+
103+
function it_calls_callable_with_request_as_argument_when_matcher_returns_true(
104+
RequestMatcher $matcher,
105+
RequestInterface $request,
106+
ResponseInterface $response
107+
) {
108+
$matcher->matches($request)->willReturn(true);
109+
110+
$this->on(
111+
$matcher,
112+
function(RequestInterface $request) use ($response) {
113+
return $response->getWrappedObject();
114+
}
115+
);
116+
117+
$this->sendRequest($request)->shouldReturn($response);
118+
}
119+
120+
function it_has_completed_sequence_when_no_matches_have_been_configured()
121+
{
122+
$this->hasCompletedSequence()->shouldReturn(true);
123+
}
124+
125+
function it_has_not_completed_sequence_when_not_all_expected_requests_have_been_sent(
126+
RequestMatcher $firstMatcher,
127+
RequestInterface $firstRequest,
128+
ResponseInterface $firstResponse,
129+
RequestMatcher $secondMatcher,
130+
RequestInterface $secondRequest,
131+
ResponseInterface $secondResponse
132+
) {
133+
$firstMatcher->matches($firstRequest)->willReturn(true);
134+
135+
$this->on($firstMatcher, $firstResponse);
136+
137+
$secondMatcher->matches($secondRequest)->willReturn(true);
138+
139+
$this->on($secondMatcher, $secondResponse);
140+
141+
$this->sendRequest($firstRequest);
142+
143+
$this->hasCompletedSequence()->shouldReturn(false);
144+
}
145+
146+
function it_has_completed_sequence_when_all_expected_requests_have_been_sent(
147+
RequestMatcher $firstMatcher,
148+
RequestInterface $firstRequest,
149+
ResponseInterface $firstResponse,
150+
RequestMatcher $secondMatcher,
151+
RequestInterface $secondRequest,
152+
ResponseInterface $secondResponse
153+
) {
154+
$firstMatcher->matches($firstRequest)->willReturn(true);
155+
156+
$this->on($firstMatcher, $firstResponse);
157+
158+
$secondMatcher->matches($secondRequest)->willReturn(true);
159+
160+
$this->on($secondMatcher, $secondResponse);
161+
162+
$this->sendRequest($firstRequest);
163+
$this->sendRequest($secondRequest);
164+
165+
$this->hasCompletedSequence()->shouldReturn(true);
166+
}
167+
}

Diff for: src/Exception/RequestMismatchException.php

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Http\Mock\Exception;
4+
5+
class RequestMismatchException extends \RuntimeException
6+
{
7+
/**
8+
* @param \Exception $exception
9+
*
10+
* @return self
11+
*/
12+
public static function fromMatcherException(\Exception $exception)
13+
{
14+
return new self(
15+
'Expected a different request to be sent.',
16+
0,
17+
$exception
18+
);
19+
}
20+
21+
/**
22+
* @return self
23+
*/
24+
public static function create()
25+
{
26+
return new self('Expected a different request to be sent.');
27+
}
28+
}

Diff for: src/Exception/UnexpectedRequestException.php

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace Http\Mock\Exception;
4+
5+
use Psr\Http\Message\RequestInterface;
6+
7+
class UnexpectedRequestException extends \RuntimeException
8+
{
9+
/**
10+
* @var RequestInterface|null
11+
*/
12+
private $request;
13+
14+
/**
15+
* @param RequestInterface $request
16+
*
17+
* @return self
18+
*/
19+
public static function fromRequest(RequestInterface $request)
20+
{
21+
$instance = new self('Did not expect request to be sent');
22+
23+
$instance->request = $request;
24+
25+
return $instance;
26+
}
27+
28+
/**
29+
* @return RequestInterface|null
30+
*/
31+
public function getRequest()
32+
{
33+
return $this->request;
34+
}
35+
}

0 commit comments

Comments
 (0)