HttpTest.php 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <?php
  2. namespace think\tests;
  3. use Mockery as m;
  4. use Mockery\MockInterface;
  5. use org\bovigo\vfs\vfsStream;
  6. use PHPUnit\Framework\TestCase;
  7. use think\App;
  8. use think\Config;
  9. use think\Console;
  10. use think\Event;
  11. use think\Exception;
  12. use think\exception\Handle;
  13. use think\Http;
  14. use think\Log;
  15. use think\Request;
  16. use think\Response;
  17. use think\Route;
  18. use think\Session;
  19. class HttpTest extends TestCase
  20. {
  21. /** @var App|MockInterface */
  22. protected $app;
  23. /** @var Http|MockInterface */
  24. protected $http;
  25. protected function tearDown(): void
  26. {
  27. m::close();
  28. }
  29. protected function setUp()
  30. {
  31. $this->app = m::mock(App::class)->makePartial();
  32. $this->http = m::mock(Http::class, [$this->app])->shouldAllowMockingProtectedMethods()->makePartial();
  33. }
  34. protected function prepareApp($request, $response)
  35. {
  36. $this->app->shouldReceive('instance')->once()->with('request', $request);
  37. $this->app->shouldReceive('initialized')->once()->andReturnFalse();
  38. $this->app->shouldReceive('initialize')->once();
  39. $this->app->shouldReceive('get')->with('request')->andReturn($request);
  40. $route = m::mock(Route::class);
  41. $route->shouldReceive('dispatch')->withArgs(function ($req, $withRoute) use ($request) {
  42. if ($withRoute) {
  43. $withRoute();
  44. }
  45. return $req === $request;
  46. })->andReturn($response);
  47. $route->shouldReceive('config')->with('route_annotation')->andReturn(true);
  48. $this->app->shouldReceive('get')->with('route')->andReturn($route);
  49. $console = m::mock(Console::class);
  50. $console->shouldReceive('call');
  51. $this->app->shouldReceive('get')->with('console')->andReturn($console);
  52. }
  53. public function testRun()
  54. {
  55. $root = vfsStream::setup('rootDir', null, [
  56. 'app' => [
  57. 'controller' => [],
  58. 'middleware.php' => '<?php return [];',
  59. ],
  60. 'route' => [
  61. 'route.php' => '<?php return [];',
  62. ],
  63. ]);
  64. $this->http->multi(false);
  65. $this->app->shouldReceive('getBasePath')->andReturn($root->getChild('app')->url() . DIRECTORY_SEPARATOR);
  66. $this->app->shouldReceive('getRootPath')->andReturn($root->url() . DIRECTORY_SEPARATOR);
  67. $request = m::mock(Request::class)->makePartial();
  68. $response = m::mock(Response::class)->makePartial();
  69. $this->prepareApp($request, $response);
  70. $this->assertEquals($response, $this->http->run($request));
  71. $this->assertFalse($this->http->isMulti());
  72. }
  73. /**
  74. * @param $request
  75. * @param $auto
  76. * @param $name
  77. * @dataProvider multiAppRunProvider
  78. */
  79. public function testMultiAppRun($request, $auto, $name, $path = null)
  80. {
  81. $root = vfsStream::setup('rootDir', null, [
  82. 'app' => [
  83. 'middleware.php' => '<?php return [];',
  84. 'app1' => [
  85. 'common.php' => '',
  86. 'event.php' => '<?php return ["bind"=>[],"listen"=>[],"subscribe"=>[]];',
  87. 'provider.php' => '<?php return [];',
  88. 'middleware.php' => '<?php return [];',
  89. 'config' => [
  90. 'app.php' => '<?php return [];',
  91. ],
  92. ],
  93. ],
  94. 'config' => [
  95. 'app.php' => '<?php return [];',
  96. 'app1' => [
  97. 'app.php' => '<?php return [];',
  98. ],
  99. ],
  100. 'route' => [
  101. 'route.php' => '<?php return [];',
  102. ],
  103. ]);
  104. $config = m::mock(Config::class)->makePartial();
  105. $config->shouldReceive('get')->with('app.auto_multi_app', false)->andReturn($auto);
  106. $config->shouldReceive('get')->with('app.domain_bind', [])->andReturn([
  107. 'www.domain.com' => 'app1',
  108. 'app2' => 'app2',
  109. ]);
  110. $config->shouldReceive('get')->with('app.app_map', [])->andReturn([
  111. 'some1' => 'app3',
  112. ]);
  113. $this->app->shouldReceive('get')->with('config')->andReturn($config);
  114. $this->app->shouldReceive('getBasePath')->andReturn($root->getChild('app')->url() . DIRECTORY_SEPARATOR);
  115. $this->app->shouldReceive('getRootPath')->andReturn($root->url() . DIRECTORY_SEPARATOR);
  116. $this->app->shouldReceive('getConfigPath')->andReturn($root->getChild('config')->url() . DIRECTORY_SEPARATOR);
  117. $response = m::mock(Response::class)->makePartial();
  118. $this->prepareApp($request, $response);
  119. $this->assertTrue($this->http->isMulti());
  120. if (null === $name) {
  121. $this->http->shouldReceive('reportException')->once();
  122. $this->http->shouldReceive('renderException')->once()->andReturn($response);
  123. }
  124. if (!$auto) {
  125. $this->http->name($name);
  126. }
  127. if ($path) {
  128. $this->http->path($path);
  129. }
  130. $this->assertEquals($response, $this->http->run($request));
  131. if (null !== $name) {
  132. $this->assertEquals($name, $this->http->getName());
  133. }
  134. if ('app1' === $name || 'app2' === $name) {
  135. $this->assertTrue($this->http->isBindDomain());
  136. }
  137. if ($path) {
  138. $this->assertEquals(rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR, $this->app->getAppPath());
  139. }
  140. }
  141. public function multiAppRunProvider()
  142. {
  143. $request1 = m::mock(Request::class)->makePartial();
  144. $request1->shouldReceive('subDomain')->andReturn('www');
  145. $request1->shouldReceive('host')->andReturn('www.domain.com');
  146. $request2 = m::mock(Request::class)->makePartial();
  147. $request2->shouldReceive('subDomain')->andReturn('app2');
  148. $request2->shouldReceive('host')->andReturn('app2.domain.com');
  149. $request3 = m::mock(Request::class)->makePartial();
  150. $request3->shouldReceive('pathinfo')->andReturn('some1/a/b/c');
  151. $request4 = m::mock(Request::class)->makePartial();
  152. $request4->shouldReceive('pathinfo')->andReturn('app3/a/b/c');
  153. $request5 = m::mock(Request::class)->makePartial();
  154. $request5->shouldReceive('pathinfo')->andReturn('some2/a/b/c');
  155. return [
  156. [$request1, true, 'app1'],
  157. [$request2, true, 'app2'],
  158. [$request3, true, 'app3'],
  159. [$request4, true, null],
  160. [$request5, true, 'some2', 'path'],
  161. [$request1, false, 'some3'],
  162. ];
  163. }
  164. public function testRunWithException()
  165. {
  166. $request = m::mock(Request::class);
  167. $response = m::mock(Response::class);
  168. $this->app->shouldReceive('instance')->once()->with('request', $request);
  169. $exception = new Exception();
  170. $this->http->shouldReceive('runWithRequest')->once()->with($request)->andThrow($exception);
  171. $handle = m::mock(Handle::class);
  172. $handle->shouldReceive('report')->once()->with($exception);
  173. $handle->shouldReceive('render')->once()->with($request, $exception)->andReturn($response);
  174. $this->app->shouldReceive('make')->with(Handle::class)->andReturn($handle);
  175. $response->shouldReceive('setCookie')->andReturn($response);
  176. $this->assertEquals($response, $this->http->run($request));
  177. }
  178. public function testEnd()
  179. {
  180. $response = m::mock(Response::class);
  181. $event = m::mock(Event::class);
  182. $event->shouldReceive('trigger')->once()->with('HttpEnd', $response);
  183. $this->app->shouldReceive('get')->once()->with('event')->andReturn($event);
  184. $log = m::mock(Log::class);
  185. $log->shouldReceive('save')->once();
  186. $this->app->shouldReceive('get')->once()->with('log')->andReturn($log);
  187. $session = m::mock(Session::class);
  188. $session->shouldReceive('save')->once();
  189. $this->app->shouldReceive('get')->once()->with('session')->andReturn($session);
  190. $this->http->end($response);
  191. }
  192. }