Testing methods in abstract classes with arguments - php

In my TDD project I am trying to test a method in an abstract class.
abstract class Database_Mapper_Abstract
{
public function setTable($sTablename){
return('foo');
}
}
This is the way I wrote my simple test:
public function testCanSetTable(){
$oMock = $this->getMockForAbstractClass('JCMS_Database_Mapper_Abstract');
$oMock->expects($this->once())
->method('setTable')
->with($this->equalTo('foo'))
->will($this->returnValue('foo'));
$this->assertEquals('foo',$oMock->setTable());
}
When I run this test i get the following error:
PHPUnit 3.5.13 by Sebastian Bergmann.
E
Time: 1 second, Memory: 6.75Mb
There was 1 error:
1)
Database_Mapper_AbstractTest::testCanSetTable
Missing argument 1 for
Database_Mapper_Abstract::setTable(), called in
K:\xampp\htdocs\tests\library\Database\Mapper\Abstract.php
on line 15 and defined
K:\xampp\htdocs\library\Database\Mapper\Abstract.php:4
K:\xampp\htdocs\tests\library\Database\Mapper\Abstract.php:15
FAILURES! Tests: 1, Assertions: 0,
Errors: 1.
The way I understand this is that it can't find the argument for the setTable function.
But I set it with the with() method. I also tried with('foo'). That also doesn't help me.
Does anyone have an idea?

Testing an abstract class:
For testing an abstract class you don't want to use the "create behavior methods".
Just getMockForAbstractClass() like this:
<?php
abstract class JCMS_Database_Mapper_Abstract
{
public function setTable($sTablename){
return $sTablename."_test";
}
}
class myTest extends PHPUnit_Framework_TestCase {
public function testCanSetTable(){
$oMock = $this->getMockForAbstractClass('JCMS_Database_Mapper_Abstract');
$this->assertEquals('foo_test', $oMock->setTable('foo'));
}
}
You just use the mocking functionality to create an instance of that abstract class and test against that.
It's only a shortcut for writing
class MyDataMapperAbstractTest extends JCMS_Database_Mapper_Abstract {
// and filling out the methods
}
The actual error:
What happens is that you have a method with one parameter:
public function setTable($sTablename){
but you call it with zero paremters:
$oMock->setTable()
so you get an error from PHP and if PHP throws a warnings PHPUnit will show you an error.
Reproduce:
<?php
abstract class JCMS_Database_Mapper_Abstract
{
public function setTable($sTablename){
return('foo');
}
}
class myTest extends PHPUnit_Framework_TestCase {
public function testCanSetTable(){
$oMock = $this->getMockForAbstractClass('JCMS_Database_Mapper_Abstract');
$oMock->expects($this->once())
->method('setTable')
->with($this->equalTo('foo'))
->will($this->returnValue('foo'));
$this->assertEquals('foo',$oMock->setTable());
}
}
Results in:
phpunit blub.php
PHPUnit 3.5.13 by Sebastian Bergmann.
E
Time: 0 seconds, Memory: 3.50Mb
There was 1 error:
1) myTest::testCanSetTable
Missing argument 1 for JCMS_Database_Mapper_Abstract::setTable(), called in /home/.../blub.php on line 19 and defined
Fixing
Change:
$this->assertEquals('foo',$oMock->setTable());
to
$this->assertEquals('foo',$oMock->setTable('foo'));
then you don't get a PHP Warning and it should work out :)

Related

Error: Call to undefined method DateFormatterTest::getMock()

Update: with $stub = $this->createMock('Config'); this example works, but I get a warning:
OK, but incomplete, skipped, or risky tests! Tests: 1, Assertions: 0,
Risky: 1.
In the video-tutorial this example works without any warnings. Is it possible to fix this warning?
I can't find why I am getting this error and how to fix it. This code is from a video tutorial. And in the Video it works. Maybe a typo?
Error:
c:\laragon\www\phpunit λ phpunit --colors tests\DateFormatterTest.php
PHPUnit 6.0.0 by Sebastian Bergmann and contributors.
E 1
/ 1 (100%)
Time: 35 ms, Memory: 4.00MB
There was 1 error:
1) DateFormatterTest::testFormattingDatesBasedOnConfig Error: Call to
undefined method DateFormatterTest::getMock()
C:\laragon\www\phpunit\tests\DateFormatterTest.php:10
ERRORS! Tests: 1, Assertions: 0, Errors: 1.
Here my code:
Config.php
<?php
class Config {
public function get() {
return 'd-m-Y';
}
}
DateFormatter.php
class DateFormatter {
protected $config;
public function __construct (Config $config) {
$this->config = $config;
}
public function getFormattedDate($timestamp) {
return date($this->config->get('date.format'), $timestamp);
}
}
DateFormatterTest.php
<?php
use PHPUnit\Framework\TestCase;
require_once 'C:\laragon\www\phpunit\src\DateFormatter.php';
require_once 'C:\laragon\www\phpunit\src\Config.php';
class DateFormatterTest extends TestCase {
public function testFormattingDatesBasedOnConfig() {
$stub = $this->getMock('Config');
var_dump($stub);
}
}
getMock() no longer exists in PHPUnit 6. Use createMock() or getMockBuilder() instead.

how to test if the correct function is called in phpunit

I am trying to learn how to write tests using phpunit.
In the test case i am trying to write i am testing 3 methods. Test is if method 1 returns false then call method 2 and 3 else just stop.
class MyTest {
$mock1->getMock('some class1')
$mock1->expect($this->once())
->method('method1')
->will($this->returnValue(false));
$mock2->getMock('some_class2')
$mock2->expect($this->once())
->method('method2')
$mock2->method2($arg)
$mock2->expect($this->once())
->method('method3')
$mock3->method3($arg)
}
how do i test if method 2 and 3 were called.
Currently i am getting a failure that No Test was Found
Look at the documentation, roughly this is how your class should look like:
class MyTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
//initialize objects for each method to work with
}
public function testFeature()
{
$arg = 'something';
$mock1->getMock('some class1');
$mock1->expect($this->once())
->method('method1')
->will($this->returnValue(false));
$mock2->getMock('some_class2');
$mock2->expect($this->once())
->method('method2');
$mock2->method2($arg);
$mock2->expect($this->once())
->method('method3');
//$mock3->method3($arg);
}
}

Issue running a basic phpUnit Database Test Case

I am new to PHP and trying to write a basic test case that verifies a connection to a database. Clearly I'm missing something fundamental. I understand from reading the manual online that this involves extending the PHPUnit_Extensions_Database_TestCase and implementing a couple of functions (getConnection() and getDataSet()). Please see my code below of the simplest case I could come up with to still get the head-scratching issue I'm encountering:
<?php
abstract class DBTest extends PHPUnit_Extensions_Database_TestCase
{
public function getConnection()
{
return true;
}
public function getDataSet()
{
return true;
}
}
?>
As you can see, the tests do nothing but return true. However, when I do a "phpUnit DBTest" I get the following message back:
PHPUnit 4.2.6 by Sebastian Bergmann.
F
Time: 1 ms, Memory: 7.50Mb
There was 1 failure:
1) Warning
No tests found in class "DBTest".
FAILURES!
Tests: 1, Assertions: 0, Failures: 1.
What am I missing? Any advice would help. Thanks.
PHPUnit complains about not finding any test. You must add at least a test method:
<?php
abstract class DBTest extends PHPUnit_Extensions_Database_TestCase
{
public function getConnection()
{
return true;
}
public function getDataSet()
{
return true;
}
public function testDummy()
{
$this->assertTrue(true);
}
}
?>

PHPUnit and Mock Objects not working

I am not sure if I am doing something wrong or it is a bug with PHPUnit and mock objects. Basically I am trying to test if $Model->doSomething() is called when $Model->start() is triggered.
I am using Ubuntu in a VirtualBox, and phpunit 1.1.1 installed via pear.
The full code is below. Any help would be appreciated, it's driving me crazy.
<?php
require_once 'PHPUnit/Autoload.php';
class Model
{
function doSomething( ) {
echo 'Hello World';
}
function doNothing( ) { }
function start( ) {
$this->doNothing();
$this->doSomething();
}
}
class ModelTest extends PHPUnit_Framework_TestCase
{
function testDoSomething( )
{
$Model = $this->getMock('Model');
$Model->expects($this->once())->method('start'); # This works
$Model->expects($this->once())->method('doSomething'); # This does not work
$Model->start();
}
}
?>
The output from PHPUnit:
There was 1 failure:
1) ModelTest::testDoSomething
Expectation failed for method name is equal to <string:doSomething> when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
As you found, you need to tell PHPUnit which methods to mock. Also, I would avoid creating expectations for methods that you are calling directly from the test. I would write the above test like this:
function testDoSomething( )
{
$Model = $this->getMock('Model', array('doSomething');
$Model->expects($this->once())->method('doSomething');
$Model->start();
}
Just to expand on why David Harkness's answer works, if you do not specify the $methods parameter to getMock then all functions in the class are mocked. Incidentally, you can confirm this with:
class ModelTest extends PHPUnit_Framework_TestCase
{
function testDoSomething( )
{
$obj = $this->getMock('Model');
echo new ReflectionClass(get_class($obj));
...
}
}
So, why does it fail? Because your start() function has been mocked too! I.e. the function body you have given has been replaced, and so your $this->doSomething(); line never gets run.
Hence, when there are any functions in your class that you need to be preserved, you'll have to explicitly give the list of all other functions.

using phpunit with yii - parent classes are not being recognized

I wrote a little test case for a model I created in Yii and when I try to run the test, it gives me: Fatal error: Class
'.....\ActiveRecord' not found in Commissions.php'
Now, my class (commissions.php) inherits the ActiveRecord class in Yii but how can I tell PHPunit where to find it? I've tried using an include statement in Commissions.php but then it can't find the class that ActiveRecord inherits and so on.
<?php
include_once('Commissions.php');
class CommissionsTest extends PHPUnit_Framework_TestCase
{
// Here, the idea would be to check one or two employees manually or based on the SQL query
// Or even a previous value using the function so that when any changes are made, the value
// remains the same while using the same arguments.
public function setUp()
{
$this->employee = new Commissions();
$this->employee->employeeId = 'V1S';
$this->employee->year = 2012;
$this->employee->period = 1;
}
public function testAttributes()
{
$this->assertEquals('V1S', $this->employee->employeeId);
$this->assertEquals(2012, $this->employee->year);
$this->assertEquals(1, $this->employee->period);
}
}
?>
What you should have at the beginning of your testcase is:
Yii:import('application.models.Commissions'); //or whatever your model is called
class CommissionsTest extends CDbTestCase { //Not PHPUnit_Framework_TestCase

Categories