Skip to content

Commit

Permalink
Use a concrete class to test AbstractRule
Browse files Browse the repository at this point in the history
Although testing abstract classes is good, using mocks makes the code
too complicated.

Signed-off-by: Henrique Moody <[email protected]>
  • Loading branch information
henriquemoody committed Jan 28, 2024
1 parent ae1620b commit 0c7f269
Showing 1 changed file with 69 additions and 100 deletions.
169 changes: 69 additions & 100 deletions tests/unit/Rules/AbstractRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,178 +10,147 @@
namespace Respect\Validation\Rules;

use Respect\Validation\Exceptions\ValidationException;
use Respect\Validation\Message\Formatter;
use Respect\Validation\Message\Stringifier\KeepOriginalStringName;
use Respect\Validation\Test\Rules\Stub;
use Respect\Validation\Test\TestCase;

use function random_int;

/**
* @covers \Respect\Validation\Rules\AbstractRule
*/
final class AbstractRuleTest extends TestCase
{
/**
* @dataProvider providerForTrueAndFalse
* @covers \Respect\Validation\Rules\AbstractRule::__invoke
* @covers \Respect\Validation\Rules\AbstractRule::__invoke
* @test
*/
public function magicMethodInvokeCallsValidateWithInput(bool $booleanResult): void
public function itShouldValidateSomeValidInputUsingTheInvokeMagicMethod(): void
{
$input = 'something';
$sut = new Stub(true);

self::assertTrue($sut('something'));
}

/**
* @covers \Respect\Validation\Rules\AbstractRule::__invoke
* @test
*/
public function itShouldValidateSomeInvalidInputUsingTheInvokeMagicMethod(): void
{
$sut = new Stub(false);

$abstractRuleMock = $this
->getMockBuilder(AbstractRule::class)
->getMockForAbstractClass();

$abstractRuleMock
->expects(self::once())
->method('validate')
->with($input)
->will(self::returnValue($booleanResult));

self::assertEquals(
$booleanResult,
// Invoking it to trigger __invoke
$abstractRuleMock($input),
'When invoking an instance of AbstractRule, the method validate should' .
'be called with the same input and return the same result.'
);
self::assertFalse($sut('something'));
}

/**
* @covers \Respect\Validation\Rules\AbstractRule::assert
* @test
*/
public function assertInvokesValidateOnSuccess(): void
public function itShouldThrowAnExceptionOnAssertingSomeInvalidInput(): void
{
$input = 'something';

$abstractRuleMock = $this
->getMockBuilder(AbstractRule::class)
->onlyMethods(['validate', 'reportError'])
->getMockForAbstractClass();

$abstractRuleMock
->expects(self::once())
->method('validate')
->with($input)
->will(self::returnValue(true));
$sut = new Stub(false);

$abstractRuleMock
->expects(self::never())
->method('reportError');
$this->expectException(ValidationException::class);

$abstractRuleMock->assert($input);
$sut->assert($input);
}

/**
* @covers \Respect\Validation\Rules\AbstractRule::assert
* @test
*/
public function assertInvokesValidateAndReportErrorOnFailure(): void
public function itShouldNotThrowAnExceptionOnAssertingSomeValidInput(): void
{
$input = 'something';
$exception = new ValidationException(
$input,
'abstract',
[],
new Formatter('strval', new KeepOriginalStringName())
);

$abstractRuleMock = $this
->getMockBuilder(AbstractRule::class)
->onlyMethods(['validate', 'reportError'])
->getMockForAbstractClass();

$abstractRuleMock
->expects(self::once())
->method('validate')
->with($input)
->will(self::returnValue(false));

$abstractRuleMock
->expects(self::once())
->method('reportError')
->with($input)
->will(self::throwException($exception));

$this->expectExceptionObject($exception);

$abstractRuleMock->assert($input);

$sut = new Stub(true);

$this->expectNotToPerformAssertions();

$sut->assert($input);
}

/**
* @covers \Respect\Validation\Rules\AbstractRule::check
* @test
*/
public function checkInvokesAssertToPerformTheValidationByDefault(): void
public function itShouldThrowAnExceptionOnCheckingSomeInvalidInput(): void
{
$input = 'something';

$abstractRuleMock = $this
->getMockBuilder(AbstractRule::class)
->onlyMethods(['assert'])
->getMockForAbstractClass();
$sut = new Stub(false);

$abstractRuleMock
->expects(self::once())
->method('assert')
->with($input);
$this->expectException(ValidationException::class);

$abstractRuleMock->check($input);
$sut->check($input);
}

/**
* @covers \Respect\Validation\Rules\AbstractRule::check
* @test
*/
public function itShouldNotThrowAnExceptionOnCheckingSomeValidInput(): void
{
$input = 'something';

$sut = new Stub(true);

$this->expectNotToPerformAssertions();

$sut->check($input);
}

/**
* @covers \Respect\Validation\Rules\AbstractRule::setTemplate
* @test
*/
public function shouldReturnTheCurrentObjectWhenDefinigTemplate(): void
public function itShouldReturnSelfWhenSettingSomeTemplate(): void
{
$abstractRuleMock = $this
->getMockBuilder(AbstractRule::class)
->getMockForAbstractClass();
$sut = new Stub();

self::assertSame($abstractRuleMock, $abstractRuleMock->setTemplate('whatever'));
self::assertSame($sut, $sut->setTemplate('whatever'));
}

/**
* @covers \Respect\Validation\Rules\AbstractRule::setName
* @test
*/
public function shouldReturnTheCurrentObjectWhenDefinigName(): void
public function itShouldReturnSelfWhenSettingSomeName(): void
{
$abstractRuleMock = $this
->getMockBuilder(AbstractRule::class)
->getMockForAbstractClass();
$sut = new Stub();

self::assertSame($abstractRuleMock, $abstractRuleMock->setName('whatever'));
self::assertSame($sut, $sut->setName('whatever'));
}

/**
* @covers \Respect\Validation\Rules\AbstractRule::getName
* @covers \Respect\Validation\Rules\AbstractRule::setName
* @test
*/
public function shouldBeAbleToDefineAndRetrivedRuleName(): void
public function itShouldBeAbleToRetrieveItsName(): void
{
$abstractRuleMock = $this
->getMockBuilder(AbstractRule::class)
->getMockForAbstractClass();

$name = 'something';

$abstractRuleMock->setName($name);
$sut = new Stub();
$sut->setName($name);

self::assertSame($name, $abstractRuleMock->getName());
self::assertSame($name, $sut->getName());
}

/**
* @return bool[][]
* @covers \Respect\Validation\Rules\AbstractRule::getName
* @test
*/
public static function providerForTrueAndFalse(): array
public function itShouldReportErrorWithExtraParameters(): void
{
return [
[true],
[false],
];
$extraParameterName = 'foo';
$extraParameterValue = random_int(1, 100);

$sut = new Stub();

$exception = $sut->reportError('input', [$extraParameterName => $extraParameterValue]);

self::assertSame($extraParameterValue, $exception->getParam($extraParameterName));
}
}

0 comments on commit 0c7f269

Please sign in to comment.