Completed
Push — master ( 3b83d2...39a0ee )
by Aimeos
03:34
created

IndexTest::testDelete()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 13
rs 9.4285
cc 1
eloc 8
nc 1
nop 0
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2016
6
 */
7
8
9
namespace Aimeos\Admin\JQAdm\Common\Decorator;
10
11
12
class IndexTest extends \PHPUnit_Framework_TestCase
13
{
14
	private $context;
15
	private $object;
16
	private $mock;
17
18
19
	protected function setUp()
20
	{
21
		$this->context = \TestHelperJqadm::getContext();
22
		$templatePaths = \TestHelperJqadm::getTemplatePaths();
23
24
		$this->mock = $this->getMockBuilder( 'Aimeos\Admin\JQAdm\Product\Standard' )
25
			->setMethods( array( 'delete', 'save' ) )
26
			->disableOriginalConstructor()
27
			->getMock();
28
29
		$this->object = new \Aimeos\Admin\JQAdm\Common\Decorator\Index( $this->mock, $this->context, $templatePaths );
30
	}
31
32
33
	protected function tearDown()
34
	{
35
		unset( $this->object, $this->mock, $this->context );
36
	}
37
38
39
	public function testDelete()
40
	{
41
		$view = \TestHelperJqadm::getView();
42
		$helper = new \Aimeos\MW\View\Helper\Param\Standard( $view, array( 'id' => 1 ) );
43
		$view->addHelper( 'param', $helper );
44
45
		$this->mock->expects( $this->once() )->method( 'delete' )->will( $this->returnValue( 'test' ) );
46
		$this->object->setView( $view );
47
48
		$result = $this->object->delete();
49
50
		$this->assertEquals( 'test', $result );
51
	}
52
53
54
	public function testSave()
55
	{
56
		$view = \TestHelperJqadm::getView();
57
		$view->item = \Aimeos\MShop\Factory::createManager( $this->context, 'product' )->findItem( 'CNC' );
1 ignored issue
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Aimeos\MShop\Common\Manager\Iface as the method findItem() does only exist in the following implementations of said interface: Aimeos\MShop\Attribute\Manager\Lists\Type\Standard, Aimeos\MShop\Attribute\Manager\Standard, Aimeos\MShop\Attribute\Manager\Type\Standard, Aimeos\MShop\Catalog\Manager\Decorator\Base, Aimeos\MShop\Catalog\Manager\Decorator\Sitecheck, Aimeos\MShop\Catalog\Manager\Lists\Type\Standard, Aimeos\MShop\Catalog\Manager\Standard, Aimeos\MShop\Common\Manager\Decorator\Base, Aimeos\MShop\Common\Manager\Decorator\Changelog, Aimeos\MShop\Common\Manager\Decorator\Sitecheck, Aimeos\MShop\Common\Manager\Type\Base, Aimeos\MShop\Coupon\Manager\Code\Standard, Aimeos\MShop\Customer\Manager\Base, Aimeos\MShop\Customer\Manager\Group\Standard, Aimeos\MShop\Customer\Manager\Lists\Type\Standard, Aimeos\MShop\Customer\Manager\Standard, Aimeos\MShop\Locale\Manager\Site\Standard, Aimeos\MShop\Media\Manager\Lists\Type\Standard, Aimeos\MShop\Media\Manager\Type\Standard, Aimeos\MShop\Plugin\Manager\Type\Standard, Aimeos\MShop\Price\Manager\Lists\Type\Standard, Aimeos\MShop\Price\Manager\Type\Standard, Aimeos\MShop\Product\Manager\Lists\Type\Standard, Aimeos\MShop\Product\Man...\Property\Type\Standard, Aimeos\MShop\Product\Manager\Standard, Aimeos\MShop\Product\Man...tock\Warehouse\Standard, Aimeos\MShop\Product\Manager\Type\Standard, Aimeos\MShop\Service\Manager\Lists\Type\Standard, Aimeos\MShop\Service\Manager\Standard, Aimeos\MShop\Service\Manager\Type\Standard, Aimeos\MShop\Supplier\Manager\Lists\Type\Standard, Aimeos\MShop\Supplier\Manager\Standard, Aimeos\MShop\Tag\Manager\Type\Standard, Aimeos\MShop\Text\Manager\Lists\Type\Standard, Aimeos\MShop\Text\Manager\Type\Standard.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
58
59
		$this->mock->expects( $this->once() )->method( 'save' )->will( $this->returnValue( 'test' ) );
60
		$this->object->setView( $view );
61
62
		$result = $this->object->save();
63
64
		$this->assertEquals( 'test', $result );
65
	}
66
}
67