0

I want to test one of my Model classes, so i have to insert, update and delete data from my database in order to test if my methods work well.

I am working with a defined Test database where i have already some data. To test all methos i use two roles, the admin one and the user one. So i get their data using the setUp method like this:

public function setUp() {
    parent::setUp();
    $this->User = ClassRegistry::init('User');

    $admin = $this->User->query("select * from users where admin = 1");
    $this->testUser['admin']['id'] = $admin[0]['users']['id'];
    $this->testUser['admin']['username'] = $admin[0]['users']['username'];
    $this->testUser['admin']['password'] = $admin[0]['users']['password'];
    $this->testUser['admin']['verified'] = $admin[0]['users']['verified'];
    $this->testUser['admin']['created'] = $admin[0]['users']['created'];
    $this->testUser['admin']['nick'] = $admin[0]['users']['nick'];
    $this->testUser['admin']['admin'] = $admin[0]['users']['admin'];

    $user = $this->User->query("select * from users where admin = 0 and verified = 0");

    $this->testUser['user']['id'] = $user[0]['users']['id'];
    $this->testUser['user']['username'] = $user[0]['users']['username'];
    $this->testUser['user']['password'] = $user[0]['users']['password'];
    $this->testUser['user']['verified'] = $user[0]['users']['verified'];
    $this->testUser['user']['created'] = $user[0]['users']['created'];
    $this->testUser['user']['nick'] = $user[0]['users']['nick'];
    $this->testUser['user']['admin'] = $user[0]['users']['admin'];

}

When i want to test methods like the "banAccess" one who moves data from the Users table to the bannedUsers table, then i have a problem because the Test won't run well the next time as the user i selected for the Test won't be in the same table. It seems that setUP() and tearDown() methods are only executed once after all test methods are called. This way, if the bannAccess test methods is executed before the testGetUserName method, for example, this last one will fail as the user is not on Users table.

For the moment i am testing the method and deleting the user after it in order to solve this problem but i am sure it have to be a better way to do it:

public function testBanAccess() {
    $result = $this->User->banAccess($this->testUser['user']['id'], 'spam', '42');
    $expected = true;

    $this->assertEquals($expected, $result);

    $this->User->query("delete from banUsers where id = ".$this->testUser['user']['id']);
}

Thanks.

1 Answer 1

1

Your whole test setup is not good. You should use fixtures for that an have the records present in the fixtures. See http://book.cakephp.org/2.0/en/development/testing.html#fixtures

setUp() and tearDown() are executed only one time while startTest() and endTest() are for each test*() method.

Further you should not use query() because it is potentially unsafe because of SQL injections. The CakePHP ORM will take care of that if you would use it... To see query() present in the test make me think you've used it in the app to and built a pretty unsafe app.

Also why do you have to copy users to another table instead simply flagging them as banned with a simple tinyint field?

Sign up to request clarification or add additional context in comments.

6 Comments

are you sure, burzum? I once wrote a test script for cake2 which told me that setUp and tearDown are run before and after each starTest/endTest and therefore also before and after each test* method.
Yeah, i am using $this->query inside all my models. What else can i use then? About the fixtures stuff, it seems like a bit boring to write all of the data again instead of getting it from the DB... So, for what i am doing right now, i should use startTest and endTest uh? And well, i am moving them to another table because they have other fields such as "reason", "expireDate". And i think it's a better DB design if i dont want to have those 2 fields at NULL in the rest of the non-banned users.
@mark I've checked checked the API on that before I posted here because I never can remember all the methods. But I will check the code when I have time later today. Steve I disagree about the db design plus you will just end up with two very similar models and very likely duplicate code. What else than query() huh? Did you read about what a framework is and does? book.cakephp.org/2.0/en/models.html start reading here. You should use Model::find() for everything, it will take care of proper escaping and your code will still work if you switch from mysql to oracle (if proper used).
I didn't start well from the start so now i have queries acceding more than one or more than 2 tables. As far as i know, models are only designed to work with only one table.
By the way, i think i toook the idea from here: book.cakephp.org/1.3/view/1027/query Anyway, using Data-sanitization (book.cakephp.org/2.0/en/core-utility-libraries/sanitize.html) would avoid that security problems right?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.