Reputation: 59
Variable $this->id
not visible in another function testExemple
If I pass this variable to a normal function that does not start on a “test” and not to a testing function, everything will work.
Can I fix this somehow?
class LoginTest extends TestCase
{
protected $id;
public function testLogin()
{
$response = $this->json('post', 'auth/login',
['email' => '[email protected]', 'password' => '12345678'])
->assertJsonStructure(['data' => ['id', 'name', 'email']]);
$response->assertStatus(201);
$userData = $response->getContent();
$userData = json_decode($userData, true);
$this->id = $userData['data']['id'];
}
public function testExemple()
{
echo($this->id);
}
}
Upvotes: 3
Views: 2518
Reputation: 568
Lets suppose you want to pass $number
from test1 to test2 :
class Test extends TestCase
{
public function test1()
{
$number = 1;
// store the variable, only available during testsuite execution,
// it does not necessarily have to exist in your .env file .
putenv('MY_NUMBER=' . $number);
//success
$this->assertEquals(getenv('MY_NUMBER'), $number);
}
public function test2()
{
//hurray ! variable retrieved
$this->assertEquals(1, getenv('MY_NUMBER'));
// after tearing down , MY_NUMBER is cleared
}
}
The solution may not be the best, but at least it works. And hey, we are doing testing, not writting production code, so who cares?
Upvotes: 1
Reputation: 40690
Each test runs independently as far as I know, if you want to pass data from one test to another you can use the @depends
doc comment like below:
class LoginTest extends TestCase
{
public function testLogin()
{
$response = $this->json('post', 'auth/login',
['email' => '[email protected]', 'password' => '12345678'])
->assertJsonStructure(['data' => ['id', 'name', 'email']]);
$response->assertStatus(201);
$userData = $response->getContent();
$userData = json_decode($userData, true);
return $userData['data']['id']; //Return this for the dependent tests
}
/**
* @depends testLogin
*/
public function testExample($id)
{
echo($id);
}
}
However the problem you might encounter is that while the $id
has a value the user is not actually logged in during this test because everything else (e.g. session) will be wiped clean.
To ensure the user is logged in then you will need to mock user login like below:
public function testExample()
{
$this->actingAs(User::where('email', '[email protected]')->first()); //User now logged in
echo(\Auth::id());
}
This ensures the user is logged in and also decouples tests.
Upvotes: 8
Reputation: 11182
It works like this because unit tests should be indepedent. A variable set by one test should never be accessible for the next.
If your issue is that you need to test things that requires you to be logged in, a good solution is creating a new class that extends TestCase
and implementing helper functions such as loginUser()
(which could return a User instance).
You should then have your tests extend this new class instead of directly extending TestCase.
Every time you run a test that requires you to log in, you can just write $this->loginUser()
and go ahead with your real test.
If all tests in a class requires you to log in, you can even add a setUp() function that will run right before any test is executed (remember to also call parrent::setUp()
:
protected function setUp() {
parent::setUp();
$this->loginUser();
}
Upvotes: 2