createNoOpMock( RateLimiter::class, [ 'limit' ] ); $expectedArgs = [ [ 'edit', 1, false ], [ 'linkpurge', 0, false ], [ 'editcontentmodel', 1, $fail ] ]; $mock->expects( $this->exactly( 3 ) ) ->method( 'limit' ) ->willReturnCallback( function ( $_, $action, $incrBy ) use ( &$expectedArgs ) { $curExpectedArgs = array_shift( $expectedArgs ); $this->assertSame( $curExpectedArgs[0], $action ); $this->assertSame( $curExpectedArgs[1], $incrBy ); return $curExpectedArgs[2]; } ); return $mock; } public function testPass() { $limiter = $this->getRateLimiter( false ); $subject = new RateLimitSubject( new UserIdentityValue( 1, 'test' ), null, [] ); $constraint = new UserRateLimitConstraint( $limiter, $subject, 'OldContentModel', 'NewContentModel' ); $this->assertConstraintPassed( $constraint ); } public function testFailure() { $limiter = $this->getRateLimiter( true ); $subject = new RateLimitSubject( new UserIdentityValue( 1, 'test' ), null, [] ); $constraint = new UserRateLimitConstraint( $limiter, $subject, 'OldContentModel', 'NewContentModel' ); $this->assertConstraintFailed( $constraint, IEditConstraint::AS_RATE_LIMITED ); } }