Skip to content

Commit

Permalink
Merge pull request #11 from jdreesen/php72-phpunit8
Browse files Browse the repository at this point in the history
Upgrade to PHP ^7.2 and and PHPUnit ^8.5
  • Loading branch information
mnapoli authored Dec 12, 2019
2 parents cd71d4d + 58a361e commit 11b7547
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 81 deletions.
6 changes: 2 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ notifications:
on_success: never

php:
- 7.0
- 7.1
- 7.2
- 7.3
- 7.4
- nightly

env:
Expand All @@ -35,15 +34,14 @@ script: vendor/bin/phpunit --colors --columns 117 --no-coverage

jobs:
allow_failures:
- php: 7.3
- php: nightly
include:
- php: nightly
env: COMPOSER_FLAGS="--ignore-platform-reqs"

- stage: test with coverage
os: linux
php: 7.1
php: 7.2
env: COMPOSER_FLAGS=""
before_install: composer self-update
script: vendor/bin/phpunit --colors --coverage-text
7 changes: 2 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@
}
},
"require": {
"php": "~7.0",
"phpunit/phpunit-mock-objects": "~5.0|~6.0"
},
"require-dev": {
"phpunit/phpunit": "~6.4|~7.0"
"php": "^7.2",
"phpunit/phpunit": "^8.5"
}
}
67 changes: 19 additions & 48 deletions src/EasyMock.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

namespace EasyMock;

use PHPUnit\Framework\MockObject\Matcher\AnyInvokedCount;
use PHPUnit\Framework\MockObject\Matcher\Invocation as InvocationMatcher;
use PHPUnit\Framework\MockObject\Matcher\InvokedAtLeastOnce;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount;
use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastOnce;

/**
* Generates mock objects.
Expand All @@ -20,18 +20,14 @@ trait EasyMock
* Methods not specified in $methods will be mocked to return null (default PHPUnit behavior).
* The class constructor will *not* be called.
*
* @param string $classname The class to mock. Can also be an existing mock to mock new methods.
* @param array $methods Array of values to return, indexed by the method name.
* @param string|MockObject $classname The class to mock. Can also be an existing mock to mock new methods.
* @param array $methods Array of values to return, indexed by the method name.
*
* @return \PHPUnit\Framework\MockObject\MockObject
* @return MockObject
*/
protected function easyMock($classname, array $methods = array())
protected function easyMock($classname, array $methods = array()): MockObject
{
if ($classname instanceof MockObject) {
$mock = $classname;
} else {
$mock = $this->doCreateMock($classname);
}
$mock = $classname instanceof MockObject ? $classname : $this->createMock($classname);

foreach ($methods as $method => $return) {
$this->mockMethod($mock, $method, new AnyInvokedCount(), $return);
Expand All @@ -43,35 +39,31 @@ protected function easyMock($classname, array $methods = array())
/**
* Mock the given class by spying on method calls.
*
* This is the same as EasyMock::mock() except this assert that methods are called at
* least once.
* This is the same as EasyMock::mock() except this assert that methods are called at least once.
*
* @see easyMock()
*
* @param string $classname The class to mock. Can also be an existing mock to mock new methods.
* @param array $methods Array of values to return, indexed by the method name.
* @param string|MockObject $classname The class to mock. Can also be an existing mock to mock new methods.
* @param array $methods Array of values to return, indexed by the method name.
*
* @return \PHPUnit\Framework\MockObject\MockObject
* @return MockObject
*/
protected function easySpy($classname, array $methods = array())
protected function easySpy($classname, array $methods = array()): MockObject
{
if ($classname instanceof MockObject) {
$mock = $classname;
} else {
$mock = $this->doCreateMock($classname);
}
$mock = $classname instanceof MockObject ? $classname : $this->createMock($classname);

foreach ($methods as $method => $return) {
$this->mockMethod($mock, $method, new InvokedAtLeastOnce, $return);
$this->mockMethod($mock, $method, new InvokedAtLeastOnce(), $return);
}

return $mock;
}

private function mockMethod(MockObject $mock, $method, InvocationMatcher $invocation, $return)
abstract protected function createMock($originalClassName): MockObject;

private function mockMethod(MockObject $mock, $method, InvocationOrder $invocation, $return): void
{
$methodAssertion = $mock->expects($invocation)
->method($method);
$methodAssertion = $mock->expects($invocation)->method($method);

if (is_callable($return)) {
$methodAssertion->willReturnCallback($return);
Expand All @@ -81,25 +73,4 @@ private function mockMethod(MockObject $mock, $method, InvocationMatcher $invoca
$methodAssertion->willReturn($return);
}
}

/**
* @param string $classname
* @return MockObject
*/
private function doCreateMock($classname)
{
// PHPUnit 5.4 method
if (method_exists($this, 'createMock')) {
return $this->createMock($classname);
}

// Fallback on the deprecated method
return $this->getMock(
$classname,
array(),
array(),
'',
false
);
}
}
50 changes: 26 additions & 24 deletions tests/EasyMockTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,55 +20,54 @@ class EasyMockTest extends TestCase
/**
* @test
*/
public function should_mock_objects()
public function should_mock_objects(): void
{
/** @var ClassFixture $mock */
$mock = $this->easyMock('EasyMock\Test\Fixture\ClassFixture');
$mock = $this->easyMock(ClassFixture::class);

$this->assertInstanceOf('PHPUnit\Framework\MockObject\MockObject', $mock);
$this->assertNull($mock->foo());
}

/**
* @test
*/
public function should_skip_the_constructor()
public function should_skip_the_constructor(): void
{
/** @var ClassWithConstructor $mock */
$mock = $this->easyMock('\EasyMock\Test\Fixture\ClassWithConstructor');
$mock = $this->easyMock(ClassWithConstructor::class);

$this->assertFalse($mock->constructorCalled);
}

/**
* @test
*/
public function should_mock_interfaces()
public function should_mock_interfaces(): void
{
/** @var InterfaceFixture $mock */
$mock = $this->easyMock('EasyMock\Test\Fixture\InterfaceFixture');
$mock = $this->easyMock(InterfaceFixture::class);

$this->assertInstanceOf('PHPUnit\Framework\MockObject\MockObject', $mock);
$this->assertNull($mock->foo());
}

/**
* @test
*/
public function not_mocked_methods_should_return_null()
public function not_mocked_methods_should_return_null(): void
{
/** @var ClassFixture $mock */
$mock = $this->easyMock('EasyMock\Test\Fixture\ClassFixture');
$mock = $this->easyMock(ClassFixture::class);

$this->assertNull($mock->foo());
}

/**
* @test
*/
public function should_mock_existing_method_with_a_value()
public function should_mock_existing_method_with_a_value(): void
{
/** @var ClassFixture $mock */
$mock = $this->easyMock('EasyMock\Test\Fixture\ClassFixture', array(
$mock = $this->easyMock(ClassFixture::class, array(
'foo' => 'bar',
));

Expand All @@ -78,10 +77,10 @@ public function should_mock_existing_method_with_a_value()
/**
* @test
*/
public function should_mock_existing_method_with_a_callback()
public function should_mock_existing_method_with_a_callback(): void
{
/** @var ClassFixture $mock */
$mock = $this->easyMock('EasyMock\Test\Fixture\ClassFixture', array(
$mock = $this->easyMock(ClassFixture::class, array(
'foo' => function () {
return 'bar';
},
Expand All @@ -92,25 +91,27 @@ public function should_mock_existing_method_with_a_callback()

/**
* @test
* @expectedException \EasyMock\Test\Fixture\CustomException
* @expectedExceptionMessage My message
*/
public function should_mock_existing_method_to_throw_exception()
public function should_mock_existing_method_to_throw_exception(): void
{
/** @var ClassFixture $mock */
$mock = $this->easyMock('EasyMock\Test\Fixture\ClassFixture', array(
$mock = $this->easyMock(ClassFixture::class, array(
'foo' => new CustomException('My message'),
));

$this->expectException(CustomException::class);
$this->expectExceptionMessage('My message');

$mock->foo();
}

/**
* @test
*/
public function should_mock_new_methods_on_existing_mock()
public function should_mock_new_methods_on_existing_mock(): void
{
/** @var ClassFixture $mock */
$mock = $this->easyMock('EasyMock\Test\Fixture\ClassFixture');
$mock = $this->easyMock(ClassFixture::class);
$mock = $this->easyMock($mock, array(
'foo' => 'bar',
));
Expand All @@ -121,14 +122,15 @@ public function should_mock_new_methods_on_existing_mock()
/**
* @test
*/
public function should_allow_to_spy_method_calls()
public function should_allow_to_spy_method_calls(): void
{
$mock = $this->easySpy('EasyMock\Test\Fixture\ClassFixture', array(
/** @var ClassFixture $mock */
$mock = $this->easySpy(ClassFixture::class, array(
'foo' => 'bar',
));

// Test PHPUnit's internals to check that the spy was registered
$property = new \ReflectionProperty('\PHPUnit\Framework\TestCase', 'mockObjects');
$property = new \ReflectionProperty(TestCase::class, 'mockObjects');
$property->setAccessible(true);
$mockObjects = $property->getValue($this);

Expand All @@ -140,7 +142,7 @@ public function should_allow_to_spy_method_calls()
$mock->__phpunit_verify();
$this->fail('Exception not thrown');
} catch (ExpectationFailedException $e) {
$this->assertContains('Expected invocation at least once but it never occur', $e->getMessage());
$this->assertStringContainsString('Expected invocation at least once but it never occur', $e->getMessage());
}

// Invoke the mock: the test should now pass
Expand Down

0 comments on commit 11b7547

Please sign in to comment.