I am learning Codeception and I wonder when I should use setUp() or tearDown() and when I should use _before() or _after(). I don't see no difference. Both methods are run before or after a single test in my testfile? Thanks,
-
What's the point? The methods have exactly the same behavior, just they're from different libraries. – Gabriel Heming Jan 30 '17 at 11:40
-
But why did Codeception integrate this methods? I think there must be a reason for this. Is it so, that it is the same for Unit Test and if I go on with functional test and acceptance test I do need this methods? – astridx Jan 30 '17 at 11:48
-
Oh, that's another question, doesn't the difference, but the purpose/reason. – Gabriel Heming Jan 30 '17 at 11:58
-
Take a look at the link above. Until now, there's no need for a full answer: http://stackoverflow.com/a/13943027/1628790 – Gabriel Heming Jan 30 '17 at 12:01
-
Thank you for your answer. But now I still do not know whether it is advantageous to use the method _before () or to use the method setup() when I create unit tests with codeception. With the sentence "But why did Codeception integrate this methods" I ment not the purpose of the method setup(). I ment the methode _before(). – astridx Jan 30 '17 at 12:23
-
It's the first principle of unit test, every test must be done individually. SetUp/_before ensure that every necessary object or state had to be done before each test (db connection, file creation, object state, etc...). When you have a global state that must be clear (file, connection, object) tearDown/_after ensure that the clean is done. Or, if each method you must log the result, setUp/_before create the connection and tearDown/_after commits the result. Just it, it's a principle. If you don't need, just don't use it... – Gabriel Heming Jan 30 '17 at 12:30
1 Answers
As Gabriel Hemming has mentioned, setUp() and tearDown() are PHPUnit's way of setting up the environment before each test is run and tearing down the environment after each test is run. _before() and _after() is how codeception's way of doing this.
To answer your question, about why codeception has different set of methods for this let me refer you to codeception's documentation: http://codeception.com/docs/05-UnitTests#creating-test
As you see, unlike in PHPUnit, the setUp and tearDown methods are replaced with their aliases: _before, _after.
The actual setUp and tearDown are implemented by the parent class \Codeception\TestCase\Test and set the UnitTester class up to have all the cool actions from Cept-files to be run as a part of your unit tests.
The cool actions the docs are referring to are any modules or helper classes that can now be used in your unit test.
Here is a good example of how to use modules in your unit test: http://codeception.com/docs/05-UnitTests#using-modules
Let's have an example of setting up fixture data in a unit test:
<?php
class UserRepositoryTest extends \Codeception\Test\Unit
{
/**
* @var \UnitTester
*/
protected $tester;
protected function _before()
{
// Note that codeception will delete the record after the test.
$this->tester->haveInDatabase('users', array('name' => 'miles', 'email' => 'miles@davis.com'));
}
protected function _after()
{
}
// tests
public function testUserAlreadyExists()
{
$userRepository = new UserRepository(
new PDO(
'mysql:host=localhost;dbname=test;port=3306;charset=utf8',
'testuser',
'password'
)
);
$user = new User();
$user->name = 'another name';
$user->email = 'miles@davis.com';
$this->expectException(UserAlreadyExistsException::class);
$user->save();
}
}
class User
{
public $name;
public $email;
}
class UserRepository
{
public function __construct(PDO $database)
{
$this->db = $database;
}
public function save(User $user)
{
try {
$this->db->prepare('INSERT INTO `users` (`name`, `email`) VALUES (:name, :email)')
->execute(['name' => $user->name, 'email' => $user->email]);
} catch (PDOException $e) {
if ($e->getCode() == 1062) {
throw new UserAlreadyExistsException();
} else {
throw $e;
}
}
}
}

- 1
- 1

- 245
- 2
- 7
-
-
1I would argue it is a unit test, in that it is testing that the repository class saves to the database. Maybe the UserRepository should be renamed to a PdoUserRepository, and then PdoUserRepository should implement a UserRepositoryInterface. Then you could rename the test to be PdoUserRepositoryTest. This, in my opinion, would show that it was a unit test in a better way. Regardless, the question is about codeception’s use of _before and _after methods. I feel my answer, answers that question sufficiently. – thomasstuttard Aug 17 '21 at 13:19
-
1Your answer is fully helpful and sufficient not only to answer the OPs concern but also to people who find this through a search engine. I'm just adding a comment to make things a little more accurate. To turn this integrationtest into a unittest, the classes `PDO` and `PDOException` must be replaced by mocks. "Unit" test means, you are testing a single unit. In the given code, you are testing the integration of several units (Repository and Database connection). – Daniel W. Aug 17 '21 at 13:54
-
1That’s fair, thanks for clarifying. I can definitely see your point of view. – thomasstuttard Aug 18 '21 at 19:48