Unit tests without having to depend on the database

I have read in posts and books that unit testing totally “pure” should not depend on the database.

I did the following test for a method that depends on the data in the database, and I would like to know if this is the best way.

I’m using codeception and Yii2.

class Play extends ActiveRecord
{

    /** Hidden code */

    public function calculateTotalScore()
    {
        $totalScore = 0;
        foreach ($this->rounds as $round) {
            $totalScore += $round->score;
        }
        return $totalScore;
    }

    /**
    * @return \yii\db\ActiveQuery
    */
    public function getRounds()
    {
        return $this->hasOne(Round::class, ['play_id' => 'id']);
    }
}

class PlayTest extends \Codeception\Test\Unit
{   
    public function testCalculateTotalScore()
    {
        $round = $this->make(Round::class, ['score' => 6]);
        $play = $this->make(Play::class, [
            'getRounds' => [$round, $round, $round],
        ]);
        $this->assertEquals(18, $play->calculateTotalScore());
    }
}

Is the test I implemented a good way?

1 Like

Yes I think this is a good way. One thing though is that it seams your getRounds() functions might need to be hasMany no?

I say this because your test is asserting many rounds returned as an array.

I would also test that totalScore is 0 if no rounds are returned.

They also talk about mocking activeRecord here: How to mock ActiveRecord

1 Like

You are right, this is a fictional code that I created to simulate this case, and I ended up commenting on this error.
Thank you for the link.

1 Like