app = $app = new Application(dirname(__DIR__, 2)); $app->instance('config', new Repository(['app' => ['timezone' => 'Asia/Shanghai'], 'admin_realtime' => ['enabled' => false]])); $app->instance('files', new \Illuminate\Filesystem\Filesystem()); $app->instance('path.lang', dirname(__DIR__, 2) . '/lang'); $app->register(\Illuminate\Translation\TranslationServiceProvider::class); $app->register(\Illuminate\Validation\ValidationServiceProvider::class); $app->instance(\Illuminate\Contracts\Routing\ResponseFactory::class, (new \ReflectionClass(\Illuminate\Routing\ResponseFactory::class))->newInstanceWithoutConstructor()); Request::macro('validate', function (array $rules) { return validator()->validate($this->all(), $rules); }); Facade::setFacadeApplication($app); $db = new Manager($app); $db->addConnection(['driver' => 'sqlite', 'database' => ':memory:', 'prefix' => 'bot_']); $db->setAsGlobal(); $db->bootEloquent(); $app->instance('db', $db->getDatabaseManager()); $db->schema()->create('payment_orders', function (Blueprint $t) { $t->id(); $t->string('member_id'); $t->integer('type'); $t->integer('status'); $t->string('state')->nullable(); $t->text('callback_data')->nullable(); $t->string('remark')->nullable(); $t->decimal('amount', 24, 10); $t->timestamps(); }); foreach ([[1, 1], [1, 7], [1, 2], [3, 1], [1, 0]] as [$type, $status]) { DB::table('payment_orders')->insert(['member_id' => 'm1', 'type' => $type, 'status' => $status, 'amount' => 10]); } } protected function tearDown(): void { DB::disconnect(); Facade::clearResolvedInstances(); parent::tearDown(); } private function reject(array $input): array { $this->app->instance('request', Request::create('/admin/paymentOrder/reject', 'POST', $input)); $resp = (new PaymentOrderController())->reject(); return json_decode($resp->getContent(), true); } private function orderStatus(int $id): int { return (int)DB::table('payment_orders')->where('id', $id)->value('status'); } public function test_open_orders_become_failed_with_remark(): void { $r = $this->reject(['id' => 1, 'remark' => '未付款']); $this->assertSame(0, $r['code'], $r['msg']); $this->assertSame(0, $this->reject(['id' => 2])['code']); $this->assertSame(0, $this->reject(['id' => 5])['code']); $this->assertSame([3, 3, 3], [$this->orderStatus(1), $this->orderStatus(2), $this->orderStatus(5)]); $this->assertSame('未付款', DB::table('payment_orders')->where('id', 1)->value('remark')); $this->assertSame('后台拒绝', DB::table('payment_orders')->where('id', 2)->value('remark')); } public function test_finished_or_other_type_orders_are_refused(): void { $this->assertNotSame(0, $this->reject(['id' => 3])['code']); $this->assertNotSame(0, $this->reject(['id' => 4])['code']); $this->assertSame([2, 1], [$this->orderStatus(3), $this->orderStatus(4)]); } public function test_late_success_callback_is_ignored_after_reject(): void { $this->reject(['id' => 1]); $apply = new \ReflectionMethod(PaymentOrderService::class, 'applyPayCallback'); $this->assertFalse($apply->invoke(null, PaymentOrder::find(1), '10', '2', '2', '3', [])); $this->assertSame(PaymentOrderService::STATUS_FAIL, $this->orderStatus(1)); } }