MockHttpTrait: support multiple MultiHttpClients
With mocking HTTP, we can supply an array of requests to expect, but if MultiHttpClient or Guzzle client are used, we can only supply one. Now we can mock a sequence of requests done via either of these clients. Change-Id: I350ed59af603a0504704af3265787a4be8f2dc2a
This commit is contained in:
parent
0f76e5ad26
commit
295557d1ae
2 changed files with 75 additions and 14 deletions
|
|
@ -51,6 +51,8 @@ trait MockHttpTrait {
|
|||
* or a string that will be used as the response body of a successful request.
|
||||
* If a MultiHttpClient is given, createMultiClient() is supported.
|
||||
* If a GuzzleHttp\Client is given, createGuzzleClient() is supported.
|
||||
* Array of MultiHttpClient or GuzzleHttp\Client mocks is supported, but not an array
|
||||
* that contains the mix of the two.
|
||||
* If null is given, any call to create(), createMultiClient() or createGuzzleClient()
|
||||
* will cause the test to fail.
|
||||
*/
|
||||
|
|
@ -70,6 +72,9 @@ trait MockHttpTrait {
|
|||
* or a callable producing such an MWHttpRequest,
|
||||
* or a string that will be used as the response body of a successful request.
|
||||
* If a MultiHttpClient is given, createMultiClient() is supported.
|
||||
* If a GuzzleHttp\Client is given, createGuzzleClient() is supported.
|
||||
* Array of MultiHttpClient or GuzzleHttp\Client mocks is supported, but not an array
|
||||
* that contains the mix of the two.
|
||||
* If null or a MultiHttpClient is given instead of a MWHttpRequest,
|
||||
* a call to create() will cause the test to fail.
|
||||
*
|
||||
|
|
@ -93,20 +98,20 @@ trait MockHttpTrait {
|
|||
->onlyMethods( [ 'create', 'createMultiClient', 'createGuzzleClient' ] )
|
||||
->getMock();
|
||||
|
||||
if ( $request instanceof MultiHttpClient ) {
|
||||
$mockHttpRequestFactory->method( 'createMultiClient' )
|
||||
->willReturn( $request );
|
||||
} else {
|
||||
$mockHttpRequestFactory->method( 'createMultiClient' )
|
||||
->willReturn( $this->createNoOpMock( MultiHttpClient::class ) );
|
||||
}
|
||||
|
||||
if ( $request instanceof GuzzleHttp\Client ) {
|
||||
$mockHttpRequestFactory->method( 'createGuzzleClient' )
|
||||
->willReturn( $request );
|
||||
} else {
|
||||
$mockHttpRequestFactory->method( 'createGuzzleClient' )
|
||||
->willReturn( $this->createNoOpMock( GuzzleHttp\Client::class ) );
|
||||
foreach ( [
|
||||
MultiHttpClient::class => 'createMultiClient',
|
||||
GuzzleHttp\Client::class => 'createGuzzleClient'
|
||||
] as $class => $method ) {
|
||||
if ( $request instanceof $class ) {
|
||||
$mockHttpRequestFactory->method( $method )
|
||||
->willReturn( $request );
|
||||
} elseif ( $this->isArrayOfClass( $class, $request ) ) {
|
||||
$mockHttpRequestFactory->method( $method )
|
||||
->willReturnOnConsecutiveCalls( ...$request );
|
||||
} else {
|
||||
$mockHttpRequestFactory->method( $method )
|
||||
->willReturn( $this->createNoOpMock( $class ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $request === null ) {
|
||||
|
|
@ -135,6 +140,26 @@ trait MockHttpTrait {
|
|||
return $mockHttpRequestFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether $array is an array where all elements are instances of $class.
|
||||
*
|
||||
* @internal to the trait
|
||||
* @param string $class
|
||||
* @param mixed $array
|
||||
* @return bool
|
||||
*/
|
||||
private function isArrayOfClass( string $class, $array ): bool {
|
||||
if ( !is_array( $array ) || !count( $array ) ) {
|
||||
return false;
|
||||
}
|
||||
foreach ( $array as $item ) {
|
||||
if ( !$item instanceof $class ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a fake MWHTTPRequest. The request also represents the desired response.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -238,6 +238,24 @@ class MockHttpTraitTest extends MediaWikiIntegrationTestCase {
|
|||
$this->assertSame( $expected, $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideMultiRequestData
|
||||
*/
|
||||
public function testMakeMockHttpRequestFactoryEmulatesMultipleMultiClients(
|
||||
$requests, $responses, $expected
|
||||
) {
|
||||
$clients = [
|
||||
$this->makeFakeHttpMultiClient( $responses ),
|
||||
$this->makeFakeHttpMultiClient( $responses ),
|
||||
];
|
||||
$factory = $this->makeMockHttpRequestFactory( $clients );
|
||||
foreach ( $clients as $unused ) {
|
||||
$client = $factory->createMultiClient();
|
||||
$data = $client->runMulti( $requests );
|
||||
$this->assertSame( $expected, $data );
|
||||
}
|
||||
}
|
||||
|
||||
public function provideGuzzleClientData() {
|
||||
yield [
|
||||
'Hello Wörld',
|
||||
|
|
@ -291,6 +309,24 @@ class MockHttpTraitTest extends MediaWikiIntegrationTestCase {
|
|||
$this->assertGuzzleResponse( $expected, $client->post( 'http://b.example.com' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideGuzzleClientData
|
||||
*/
|
||||
public function testMakeMockHttpRequestFactoryEmulatesMultipleGuzzleRequests( $response, $expected ) {
|
||||
$fakeClients = [
|
||||
$this->makeFakeGuzzleClient( $response ),
|
||||
$this->makeFakeGuzzleClient( $response ),
|
||||
];
|
||||
$factory = $this->makeMockHttpRequestFactory( $fakeClients );
|
||||
foreach ( $fakeClients as $unused ) {
|
||||
$client = $factory->createGuzzleClient();
|
||||
$this->assertGuzzleResponse( $expected, $client->request( 'TEST', 'http://b.example.com' ) );
|
||||
$this->assertGuzzleResponse( $expected, $client->get( 'http://b.example.com' ) );
|
||||
$this->assertGuzzleResponse( $expected, $client->put( 'http://b.example.com' ) );
|
||||
$this->assertGuzzleResponse( $expected, $client->post( 'http://b.example.com' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ResponseInterface $expected
|
||||
* @param ResponseInterface $actual
|
||||
|
|
|
|||
Loading…
Reference in a new issue