Symfony - mocking token storage interface and return user object

Viewed 306

In my service method I am mocking I have part where I am persisting entity from user table like:

$user = $this->tokenStorage->getToken()->getUser();
$userFirstName = 'Unknown user';

$new = new MyEntity();
if ($user != 'anon.') {
    $new->setUserId($user);
    $userFirstName = $user->getFirstName();
 }

I am writing that part in a separate test method where I want to return sepcific User object, meaning I want to test it..

public function testUser()
{
    $tokenStorage = $this->createMock(TokenStorageInterface::class);
    $userRepo = $this->createMock(UserRepository::class);

    $username = ['username' => 'test@test.com']; // this will find the entry in the DB

    $testUserObject = new User();

    $userRepo->expects($this->any())
    ->method('findOneBY')
    ->with($username)
    ->will($this->returnValue($testUserObject));

    $user = $tokenStorage->getToken()->getUser();
    $this->assertEquals($testUserObject, $user);
}

but I get:

Error: Call to a member function getUser() on null

and I think this is the user in my test db..

Or maybe this is not a proper way to test this case? Can someone help I am new at writing tests..

Another question is, can I use returned value of this test method and use it's user object for testing whole method where I persist this user object?

1 Answers

Regard the error, you're not saying what $tokenStorage->getToken() will return. As you're mocking the token storage, a getToken invocation you've not stubbed, ends up to return a null value.

Said that, you should really don't mock what you don't own (basically, don't mock third party code) as you can't control it. This kind of test should be improved in two ways

  1. Don't test it at unit level but at integration/functional/e2e level.

  2. Write you're own abstraction for token storage (can be useless if this is an application service rather than a domain service).

Of course no one prevents you to mock what you don't own, that's just an advice.

Regard this sentece

can I use returned value of this test method and use it's user object for testing whole method where I persist this user object

if I understand correctly, you're trying to test a private method here? If so, just don't do that and test only the public API (public methods) of your class. Instead, if this is a public method, is perfectly OK to test it even if it's used by another public method.

Related