RouteTest.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. <?php
  2. namespace think\tests;
  3. use Closure;
  4. use Mockery as m;
  5. use Mockery\MockInterface;
  6. use PHPUnit\Framework\TestCase;
  7. use think\helper\Str;
  8. use think\Request;
  9. use think\response\Redirect;
  10. use think\response\View;
  11. use think\Route;
  12. class RouteTest extends TestCase
  13. {
  14. use InteractsWithApp;
  15. /** @var Route|MockInterface */
  16. protected $route;
  17. protected function tearDown(): void
  18. {
  19. m::close();
  20. }
  21. protected function setUp(): void
  22. {
  23. $this->prepareApp();
  24. $this->config->shouldReceive('get')->with('route')->andReturn(['url_route_must' => true]);
  25. $this->route = new Route($this->app);
  26. }
  27. /**
  28. * @param $path
  29. * @param string $method
  30. * @param string $host
  31. * @return m\Mock|Request
  32. */
  33. protected function makeRequest($path, $method = 'GET', $host = 'localhost')
  34. {
  35. $request = m::mock(Request::class)->makePartial();
  36. $request->shouldReceive('host')->andReturn($host);
  37. $request->shouldReceive('pathinfo')->andReturn($path);
  38. $request->shouldReceive('url')->andReturn('/' . $path);
  39. $request->shouldReceive('method')->andReturn(strtoupper($method));
  40. return $request;
  41. }
  42. public function testSimpleRequest()
  43. {
  44. $this->route->get('foo', function () {
  45. return 'get-foo';
  46. });
  47. $this->route->put('foo', function () {
  48. return 'put-foo';
  49. });
  50. $this->route->group(function () {
  51. $this->route->post('foo', function () {
  52. return 'post-foo';
  53. });
  54. });
  55. $request = $this->makeRequest('foo', 'post');
  56. $response = $this->route->dispatch($request);
  57. $this->assertEquals(200, $response->getCode());
  58. $this->assertEquals('post-foo', $response->getContent());
  59. $request = $this->makeRequest('foo', 'get');
  60. $response = $this->route->dispatch($request);
  61. $this->assertEquals(200, $response->getCode());
  62. $this->assertEquals('get-foo', $response->getContent());
  63. }
  64. public function testGroup()
  65. {
  66. $this->route->group(function () {
  67. $this->route->group('foo', function () {
  68. $this->route->post('bar', function () {
  69. return 'hello,world!';
  70. });
  71. });
  72. });
  73. $request = $this->makeRequest('foo/bar', 'post');
  74. $response = $this->route->dispatch($request);
  75. $this->assertEquals(200, $response->getCode());
  76. $this->assertEquals('hello,world!', $response->getContent());
  77. }
  78. public function testAllowCrossDomain()
  79. {
  80. $this->route->get('foo', function () {
  81. return 'get-foo';
  82. })->allowCrossDomain(['some' => 'bar']);
  83. $request = $this->makeRequest('foo', 'get');
  84. $response = $this->route->dispatch($request);
  85. $this->assertEquals('bar', $response->getHeader('some'));
  86. $this->assertArrayHasKey('Access-Control-Allow-Credentials', $response->getHeader());
  87. //$this->expectException(RouteNotFoundException::class);
  88. $request = $this->makeRequest('foo2', 'options');
  89. $this->route->dispatch($request);
  90. }
  91. public function testControllerDispatch()
  92. {
  93. $this->route->get('foo', 'foo/bar');
  94. $controller = m::Mock(\stdClass::class);
  95. $this->app->shouldReceive('parseClass')->with('controller', 'Foo')->andReturn($controller->mockery_getName());
  96. $this->app->shouldReceive('make')->with($controller->mockery_getName(), [], true)->andReturn($controller);
  97. $controller->shouldReceive('bar')->andReturn('bar');
  98. $request = $this->makeRequest('foo');
  99. $response = $this->route->dispatch($request);
  100. $this->assertEquals('bar', $response->getContent());
  101. }
  102. public function testEmptyControllerDispatch()
  103. {
  104. $this->route->get('foo', 'foo/bar');
  105. $controller = m::Mock(\stdClass::class);
  106. $this->app->shouldReceive('parseClass')->with('controller', 'Error')->andReturn($controller->mockery_getName());
  107. $this->app->shouldReceive('make')->with($controller->mockery_getName(), [], true)->andReturn($controller);
  108. $controller->shouldReceive('bar')->andReturn('bar');
  109. $request = $this->makeRequest('foo');
  110. $response = $this->route->dispatch($request);
  111. $this->assertEquals('bar', $response->getContent());
  112. }
  113. protected function createMiddleware($times = 1)
  114. {
  115. $middleware = m::mock(Str::random(5));
  116. $middleware->shouldReceive('handle')->times($times)->andReturnUsing(function ($request, Closure $next) {
  117. return $next($request);
  118. });
  119. $this->app->shouldReceive('make')->with($middleware->mockery_getName())->andReturn($middleware);
  120. return $middleware;
  121. }
  122. public function testControllerWithMiddleware()
  123. {
  124. $this->route->get('foo', 'foo/bar');
  125. $controller = m::mock(FooClass::class);
  126. $controller->middleware = [
  127. $this->createMiddleware()->mockery_getName() . ":params1:params2",
  128. $this->createMiddleware(0)->mockery_getName() => ['except' => 'bar'],
  129. $this->createMiddleware()->mockery_getName() => ['only' => 'bar'],
  130. [
  131. 'middleware' => [$this->createMiddleware()->mockery_getName(), [new \stdClass()]],
  132. 'options' => ['only' => 'bar'],
  133. ],
  134. ];
  135. $this->app->shouldReceive('parseClass')->with('controller', 'Foo')->andReturn($controller->mockery_getName());
  136. $this->app->shouldReceive('make')->with($controller->mockery_getName(), [], true)->andReturn($controller);
  137. $controller->shouldReceive('bar')->once()->andReturn('bar');
  138. $request = $this->makeRequest('foo');
  139. $response = $this->route->dispatch($request);
  140. $this->assertEquals('bar', $response->getContent());
  141. }
  142. public function testRedirectDispatch()
  143. {
  144. $this->route->redirect('foo', 'http://localhost', 302);
  145. $request = $this->makeRequest('foo');
  146. $this->app->shouldReceive('make')->with(Request::class)->andReturn($request);
  147. $response = $this->route->dispatch($request);
  148. $this->assertInstanceOf(Redirect::class, $response);
  149. $this->assertEquals(302, $response->getCode());
  150. $this->assertEquals('http://localhost', $response->getData());
  151. }
  152. public function testViewDispatch()
  153. {
  154. $this->route->view('foo', 'index/hello', ['city' => 'shanghai']);
  155. $request = $this->makeRequest('foo');
  156. $response = $this->route->dispatch($request);
  157. $this->assertInstanceOf(View::class, $response);
  158. $this->assertEquals(['city' => 'shanghai'], $response->getVars());
  159. $this->assertEquals('index/hello', $response->getData());
  160. }
  161. public function testDomainBindResponse()
  162. {
  163. $this->route->domain('test', function () {
  164. $this->route->get('/', function () {
  165. return 'Hello,ThinkPHP';
  166. });
  167. });
  168. $request = $this->makeRequest('', 'get', 'test.domain.com');
  169. $response = $this->route->dispatch($request);
  170. $this->assertEquals('Hello,ThinkPHP', $response->getContent());
  171. $this->assertEquals(200, $response->getCode());
  172. }
  173. }
  174. class FooClass
  175. {
  176. public $middleware = [];
  177. public function bar()
  178. {
  179. }
  180. }