Giter Club home page Giter Club logo

psalm-plugin-mockery's People

Contributors

aripringle avatar batumibiz avatar dependabot[bot] avatar erunion avatar jaydiablo avatar lptn avatar mr-feek avatar muglug avatar orklah avatar villfa avatar weirdan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

psalm-plugin-mockery's Issues

Enabling the plugin hides some errors

Hi,

It seems that when the plugin is active some errors are not visible, for example with the following test class I would have expected to get an InvalidReturnType and an InvalidReturnStatement errors but instead no errors are thrown:

<?php

declare(strict_types=1);

namespace Repro;

use PHPUnit\Framework\TestCase;

final class ReproTest extends TestCase
{
    use \Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;

    public function dataProviderCoveringScopes(): bool
    {
        return ['foo'];
    }
}

I have set up a repo that can be used to reproduce: https://github.com/LeSuisse/repro-issue-psalm-mockery-issue-no-error

Strange behaviour using spy

I'm getting strange behaviour trying to use a spy.

Let me show an example:

/**
 * @psalm-suppress MissingConstructor
 */
class SpyTest extends TestCase
{
    /**
     * @test
     */
    public function spy(): void
    {
        $mockDepService = \Mockery::mock(DepService::class);
        $s1 = new Service($mockDepService);

        $spyDepService = \Mockery::spy(DepService::class);
        $s2 = new Service($spyDepService);
    }
}

class DepService
{
}

class Service
{
    public function __construct(private DepService $depService)
    {
    }
}

By running Psalm on this code I get an error on the spy but not on the mock.

ERROR: InvalidArgument - tests/SpyTest.php:23:27 - Argument 1 of Tests\Service::__construct expects Tests\DepService, Mockery\MockInterface provided (see https://psalm.dev/004)
        $s2 = new Service($spyDepService);

Am I doing something wrong?

Call to undefined method Psalm\Type\Union::getTypes()

That started happening in the last week with unchanged analyzed code.

Code that makes it crash:

$session = Mockery::mock(\Mezzio\Session\SessionInterface::class);

Changing this for the phpunit mock fixes the issue.

Stack trace:

Uncaught Error: Call to undefined method Psalm\Type\Union::getTypes() in /Volumes/Project/example-project/vendor/psalm/plugin-mockery/Hooks/MockReturnTypeUpdater.php:71
Stack trace:
#0 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php(480): Psalm\MockeryPlugin\Hooks\MockReturnTypeUpdater::afterMethodCallAnalysis(Object(PhpParser\Node\Expr\StaticCall), 'Mockery::mock', 'Mockery::mock', 'Mockery::mock', Object(Psalm\Context), Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(Psalm\Codebase), Array, Object(Psalm\Type\Union))
#1 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php(721): Psalm\Internal\Analyzer\Statements\Expression\Call\StaticMethod\ExistingAtomicStaticCallAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(PhpParser\Node\Identifier), Array, Object(Psalm\Context), Object(Psalm\Type\Atomic\TNamedObject), Object(Psalm\Internal\MethodIdentifier), 'Mockery::mock', Object(Psalm\Storage\ClassLikeStorage), false)
#2 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php(171): Psalm\Internal\Analyzer\Statements\Expression\Call\StaticMethod\AtomicStaticCallAnalyzer::handleNamedCall(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(PhpParser\Node\Identifier), Object(Psalm\Context), Object(Psalm\Type\Atomic\TNamedObject), Array, 'Mockery', false, true)
#3 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php(205): Psalm\Internal\Analyzer\Statements\Expression\Call\StaticMethod\AtomicStaticCallAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(Psalm\Context), Object(Psalm\Type\Atomic\TNamedObject), false, false, false, true)
#4 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(155): Psalm\Internal\Analyzer\Statements\Expression\Call\StaticCallAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(Psalm\Context))
#5 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(39): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::handleExpression(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(Psalm\Context), false, NULL, false)
#6 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php(197): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(Psalm\Context))
#7 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php(306): Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Array, Array, 'D4H\\Decisions\\S...', true, Object(Psalm\Context), Object(Psalm\Internal\Type\TemplateResult))
#8 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php(324): Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer::checkMethodArgs(Object(Psalm\Internal\MethodIdentifier), Array, Object(Psalm\Internal\Type\TemplateResult), Object(Psalm\Context), Object(Psalm\CodeLocation), Object(Psalm\Internal\Analyzer\StatementsAnalyzer))
#9 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php(204): Psalm\Internal\Analyzer\Statements\Expression\Call\NewAnalyzer::analyzeNamedConstructor(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(Psalm\Codebase), Object(PhpParser\Node\Expr\New_), Object(Psalm\Context), 'D4H\\Decisions\\S...', false, false)
#10 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(250): Psalm\Internal\Analyzer\Statements\Expression\Call\NewAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\New_), Object(Psalm\Context))
#11 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(39): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::handleExpression(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\New_), Object(Psalm\Context), false, NULL, false)
#12 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php(194): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\New_), Object(Psalm\Context))
#13 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(132): Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\Variable), Object(PhpParser\Node\Expr\New_), NULL, Object(Psalm\Context), NULL)
#14 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(39): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::handleExpression(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\Assign), Object(Psalm\Context), false, Object(Psalm\Context), true)
#15 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(522): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\Assign), Object(Psalm\Context), false, Object(Psalm\Context), true)
#16 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(171): Psalm\Internal\Analyzer\StatementsAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\Expression), Object(Psalm\Context), Object(Psalm\Context))
#17 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php(654): Psalm\Internal\Analyzer\StatementsAnalyzer->analyze(Array, Object(Psalm\Context), Object(Psalm\Context), true)
#18 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassAnalyzer.php(1978): Psalm\Internal\Analyzer\FunctionLikeAnalyzer->analyze(Object(Psalm\Context), Object(Psalm\Internal\Provider\NodeDataProvider), Object(Psalm\Context))
#19 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassAnalyzer.php(1646): Psalm\Internal\Analyzer\ClassAnalyzer->analyzeClassMethod(Object(PhpParser\Node\Stmt\ClassMethod), Object(Psalm\Storage\ClassLikeStorage), Object(Psalm\Internal\Analyzer\TraitAnalyzer), Object(Psalm\Context), Object(Psalm\Context))
#20 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassAnalyzer.php(758): Psalm\Internal\Analyzer\ClassAnalyzer->analyzeTraitUse(Object(Psalm\Aliases), Object(PhpParser\Node\Stmt\TraitUse), Object(Psalm\Internal\Analyzer\ProjectAnalyzer), Object(Psalm\Storage\ClassLikeStorage), Object(Psalm\Context), Object(Psalm\Context), NULL)
#21 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FileAnalyzer.php(211): Psalm\Internal\Analyzer\ClassAnalyzer->analyze(Object(Psalm\Context), Object(Psalm\Context))
#22 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php(340): Psalm\Internal\Analyzer\FileAnalyzer->analyze(NULL)
#23 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php(579): Psalm\Internal\Codebase\Analyzer->Psalm\Internal\Codebase\{closure}(91, '/Volumes/Source...')
#24 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php(269): Psalm\Internal\Codebase\Analyzer->doAnalysis(Object(Psalm\Internal\Analyzer\ProjectAnalyzer), 1)
#25 /Users/foo/.composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php(1182): Psalm\Internal\Codebase\Analyzer->analyzeFiles(Object(Psalm\Internal\Analyzer\ProjectAnalyzer), 1, false, false)
#26 /Users/foo/.composer/vendor/vimeo/psalm/src/psalm.php(678): Psalm\Internal\Analyzer\ProjectAnalyzer->checkPaths(Array)
#27 /Users/foo/.composer/vendor/vimeo/psalm/psalm(2): require_once('/Users/foo/.co...')
#28 {main}
(Psalm 4.3.1@2feba22a005a18bf31d4c7b9bdb9252c73897476 crashed due to an uncaught Throwable)

Intersection type for mocks?

I have a project that uses Mockery, and have both phpstan and psalm running against it.

I'm using this plugin and the phpstan mockery plugin (https://github.com/phpstan/phpstan-mockery) to help reduce the number of errors that have to ignored and/or worked around.

One thing that the phpstan plugin does, that this plugin doesn't seem to, is treating the Mockery\MockInterface as an intersection type when defined with another object:

Interprets Foo|\Mockery\MockInterface in phpDoc so that it results in an intersection type instead of a union type.

This allows me to do something like this:

/** @var User|\Mockery\MockInterface $user */
        $user = Mockery::mock(
            'User[oneMethod,twoMethod]',
            $constructorParams
        );

When defining mocks, and then the methods available on both User and \Mockery\MockInterface are available. So when the Mock is later used like so:

$user->shouldReceive('oneMethod')->zeroOrMoreTimes();

phpstan won't complain that the User class doesn't have the shouldReceive method. Likewise, this code also won't trigger an error:

$user->oneMethod()

Since the User object does have this method (but \Mockery\MockInterface) does not.

Is this something that could/should be added to this plugin? I can try to take a stab at it if so...

AcceptanceTester and Acceptance do not comply with PSR-4.

When installing this package with composer install -o I get a notice that there are 2 classes that do not comply with PSR-4 and will not work with Composer 2.0.

Deprecation Notice: Class Psalm\MockeryPlugin\Tests\AcceptanceTester located in ./vendor/psalm/plugin-mockery/tests/_support/AcceptanceTester.php does not comply with psr-4 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///usr/local/bin/composer/src/Composer/Autoload/ClassMapGenerator.php:201
Deprecation Notice: Class Psalm\MockeryPlugin\Tests\Helper\Acceptance located in ./vendor/psalm/plugin-mockery/tests/_support/Helper/Acceptance.php does not comply with psr-4 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///usr/local/bin/composer/src/Composer/Autoload/ClassMapGenerator.php:201

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.