Search code examples
phplaravel-4phpspec

PhpSpec return always null on mocks


I'm working with PhpSpec and for some reason when I mock my dependencies and call them the willReturn method of PhpSpec give me a null value instead of the value passed.

This is the method that I'm trying to describe

    /**
     * Register an User
     *
     * @param array $infoUser
     * @return User
     */
    public function register(array $infoUser)
    {

        $user = $this->user->create($infoUser);

        $this->raise(new UserRegistered($user));

        return $user;
    }

My Spec

class BaseAuthSpec extends ObjectBehavior
{
    function it_is_initializable()
    {
        $this->shouldHaveType('Core\Auth\BaseAuth');
    }

    function let(AuthManager $guard,UserAuthRepository $user)
    {
        $this->beConstructedWith($guard,$user);
    }

    function it_register_an_user(UserAuthRepository $useRepo)
    {
        $user = [
            'username' => 'fabri',
            'email'    => 'test@test.com',
            'password' => 'password',
            'repeat_password' => 'password'
        ];

        $userModel = new User($user);

        // this line return null instead the $userModel
        $useRepo->create($user)->shouldBeCalled()->willReturn($userModel);

        $this->raise(new UserRegistered($userModel))->shouldReturn(null);

        $this->register($user)->shouldReturn($userModel);
    }
}

I'm stuck with this issue, any suggest will be appreciated.


Solution

  • Arguments are matched by name. The user repository passed to your let() method, is not the same as passed to the it_register_an_user() method. To fix your issue, simply give it the same name.

    There're other issues in your spec.

    It's not possible to mock nor stub a method on the class you're speccing. This is not going to work:

    $this->raise(new UserRegistered($userModel))->shouldReturn(null);
    

    I'm not sure what's going on in the raise() method, but you should deal with it properly in your example, so either stub or mock any collaborators (or leave them alone if there's no return values relevant to the current example).

    Another thing is that you use mocks when what you really need is stubs. I'd rewrite your example to be:

    class BaseAuthSpec extends ObjectBehavior
    {
        function let(AuthManager $guard, UserAuthRepository $userRepo)
        {
            $this->beConstructedWith($guard, $user);
        }
    
        function it_registers_a_user(UserAuthRepository $userRepo, User $userModel)
        {
            $user = [
                'username' => 'fabri',
                'email'    => 'test@test.com',
                'password' => 'password',
                'repeat_password' => 'password'
            ];
    
            $userRepo->create($user)->willReturn($userModel);
    
            $this->register($user)->shouldReturn($userModel);
        }
    }
    

    The raise method should be covered by seperate examples.