client->disableReboot(); $mobile = '0912' . str_pad((string) random_int(0, 9_999_999), 7, '0', STR_PAD_LEFT); // a fresh random IP block per run so the persistent per-IP limiter buckets // don't accumulate across runs and fire early. $ipBase = random_int(1, 250); $statuses = []; for ($i = 0; $i < 6; $i++) { // each request from a different IP → the per-IP limiter never fires $this->client->request( 'POST', '/api/v1/user/send-code', server: ['REMOTE_ADDR' => "10.$ipBase.30.$i", 'CONTENT_TYPE' => 'application/json'], content: json_encode(['mobile' => $mobile]), ); $statuses[] = $this->client->getResponse()->getStatusCode(); } // send_code limit is 5/hour → the 6th for the same mobile is rejected $this->assertSame(429, $statuses[5], 'per-mobile cap not enforced: ' . implode(',', $statuses)); $this->assertNotContains(429, array_slice($statuses, 0, 5)); } }