Testování modelů se závislostmi

zachrdlapetr
Člen | 49
+
0
-

Potřebuji trochu nakopnout ohledně testování modelů, ale prakticky jde o jakoukoliv jinou třídu se závislostmi.

Mám následující tester s modelem bez závislosti a tohle jede normálně.

Tester

namespace Test;
use Nette;
use Tester\Assert;

$container = require './bootstrap.php';


class Test extends \Tester\TestCase {
    public $container;
    public $array;

    public function __construct(\Nette\DI\Container $container) {
		$this->container = $container;
		$this->array = $container->getByType('\App\Model\Utilities\NecoModel');
    }

    public function testTestu() {
		Assert::type('array', $this->array->get(['aaa']));
    }

}

$testcase = new Test($container);
$testcase->run();

Model bez závislosti

namespace App\Model\Utilities;

class NecoModel   {

    public function get($array) {
		return $array;
    }

}

Ale…

Pak mám model se závislostí, třeba na databázi. A tato se mi nedaří dostat do testu uvedeného výše. Pomůžete mi někdo prosím?

Model se závislostí na db

namespace App\Model\Utilities;

class NecoModel   {
	public $db;

    public function __construct(\Nette\Database\Context $db) {
		$this->db = $db;
    }

    public function get($array) {
		return $array;
    }

}
kocourPB
Člen | 47
+
+1
-

Ahoj,

pokial chces testovat testovat nejaku classu z modelu, ktora obsahuje zavislosti na inej classe (viz. v tvojom pripade \Nette\Database\Context) musis si tuto classu najskor namockovat. Hodi sa na to napr. Mockery .. example: http://docs.mockery.io/…example.html

kocourPB
Člen | 47
+
+1
-

priklad ako by to asi mohlo vyzerat:

<?php

namespace Test;

use Nette;
use Tester\Assert;


class Test extends \Tester\TestCase {

    public function testArray() {
    	$dbContextMock = \Mockery::mock('Context');
    	$necoModel = new \App\Model\Utilities\NecoModel($dbContextMock);

        Assert::type('array', $this->array->get(['aaa']));
    }

}

(new Test())->run();

Editoval kocourPB (26. 4. 2019 13:27)

David Matějka
Moderator | 6445
+
+1
-

Pokud píšeš unit testy, tak jak píše @kocourPB

Pokud však chceš psát integrační testy včetně databáze, tak to, co píšeš, by mělo fungovat. co konkrétně znamená, že se ti to nedaří? ja vytváříš ten container?

zachrdlapetr
Člen | 49
+
+1
-

kocourPB napsal(a):

super. díky za tip. mockery jsem neznal. prostuduji. funguje to skvěle.

zachrdlapetr
Člen | 49
+
+1
-

David Matějka napsal(a):

Pokud píšeš unit testy, tak jak píše @kocourPB

Pokud však chceš psát integrační testy včetně databáze, tak to, co píšeš, by mělo fungovat. co konkrétně znamená, že se ti to nedaří? ja vytváříš ten container?

bohužel měl jsem problém v testu vložit tam Nette\Database\Context nějak elegantně, protože ta třída sama o sobě vyžaduje další závislost. Mockery to vyřešila. Nebo existuje i jiný způsob jak vložit databázi do testArray() níže?

public function testArray() {
		$db = \Mockery::mock('Nette\Database\Context');
		$dbc = \Mockery::mock('Nette\Database\Connection');

		$arrayModel = new \App\Model\Utilities\ArrayModel($db, $dbc);
		Assert::type('array', $arrayModel->trimArrayRecursively(['aaa']));
}

container mám klasiku. cache a log ukládání zvlášť.

require '../vendor/autoload.php';
$configurator = new Nette\Configurator();


$configurator->enableTracy(__DIR__. '/../log_tester');
$configurator->setTimeZone('Europe/Prague');
$configurator->setTempDirectory('../temp_tester');
$configurator->createRobotLoader()
	->addDirectory('../app')
	->register();

$configurator->addConfig('../app/config/config.neon');
$configurator->addConfig('../app/config/config.local.neon');
$container = $configurator->createContainer();
return $container;