test - PHPUnit objetos falsos y métodos estáticos
symfony test app (6)
Estoy buscando la mejor manera de probar el siguiente método estático (específicamente usando un Modelo de Doctrina):
class Model_User extends Doctrine_Record
{
public static function create($userData)
{
$newUser = new self();
$newUser->fromArray($userData);
$newUser->save();
}
}
Idealmente, usaría un objeto simulado para asegurarme de que se llamaba "fromArray" (con los datos de usuario suministrados) y "save", pero eso no es posible ya que el método es estático.
¿Alguna sugerencia?
Ahora está la biblioteca AspectMock para ayudar con esto:
https://github.com/Codeception/AspectMock
$this->assertEquals(''users'', UserModel::tableName());
$userModel = test::double(''UserModel'', [''tableName'' => ''my_users'']);
$this->assertEquals(''my_users'', UserModel::tableName());
$userModel->verifyInvoked(''tableName'');
Haría una nueva clase en el espacio de nombres de la prueba de la unidad que extendería el Model_User y lo probaría. Aquí hay un ejemplo:
Clase original:
class Model_User extends Doctrine_Record
{
public static function create($userData)
{
$newUser = new self();
$newUser->fromArray($userData);
$newUser->save();
}
}
Clase falsa para llamar en pruebas unitarias:
use /Model_User
class Mock_Model_User extends Model_User
{
/** /PHPUnit/Framework/TestCase */
public static $test;
// This class inherits all the original classes functions.
// However, you can override the methods and use the $test property
// to perform some assertions.
}
En tu prueba de unidad:
use Module_User;
use PHPUnit/Framework/TestCase;
class Model_UserTest extends TestCase
{
function testCanInitialize()
{
$userDataFixture = []; // Made an assumption user data would be an array.
$sut = new Mock_Model_User::create($userDataFixture); // calls the parent ::create method, so the real thing.
$sut::test = $this; // This is just here to show possibilities.
$this->assertInstanceOf(Model_User::class, $sut);
}
}
La biblioteca doublit también podría ayudarlo a probar métodos estáticos:
/* Create a mock instance of your class */
$double = Doublit::mock_instance(Model_User::class);
/* Test the "create" method */
$double::_method(''create'')
->count(1) // test that the method is called once
->args([Constraints::isInstanceOf(''array'')]) // test that first argument is an array
->stub(''my_value'') // stub the method to return "myvalue"
Otro posible enfoque es con la biblioteca Moka :
$modelClass = Moka::mockClass(''Model_User'', [
''fromArray'' => null,
''save'' => null
]);
$modelClass::create(''DATA'');
$this->assertEquals([''DATA''], $modelClass::$moka->report(''fromArray'')[0]);
$this->assertEquals(1, sizeof($modelClass::$moka->report(''save'')));
Probar métodos estáticos generalmente se considera un poco difícil (como probablemente ya habrás notado) , especialmente antes de PHP 5.3.
¿No podría modificar su código para no usar un método estático? Realmente no veo por qué estás usando un método estático aquí, de hecho; esto probablemente podría volver a escribirse en algún código no estático, ¿no es así?
Por ejemplo, podría algo como esto no hacer el truco:
class Model_User extends Doctrine_Record
{
public function saveFromArray($userData)
{
$this->fromArray($userData);
$this->save();
}
}
No estoy seguro de lo que probará; pero, al menos, ya no hay un método estático ...
Sebastian Bergmann, el autor de PHPUnit, recientemente publicó un blog sobre Stubbing and Mocking Static Methods . Con PHPUnit 3.5 y PHP 5.3, así como el uso constante de enlaces estáticos tardíos, puede hacer
$class::staticExpects($this->any())
->method(''helper'')
->will($this->returnValue(''bar''));
Actualización: staticExpects
está en desuso a partir de PHPUnit 3.8 y se eliminará por completo con las versiones posteriores.