SlideShare ist ein Scribd-Unternehmen logo
1 von 43
Downloaden Sie, um offline zu lesen
Stub you!
Andrea Giuliano
@bit_shark
mercoledì 26 giugno 13
When you’re doing testing
you’re focusing on one element at a time
Unit testing
mercoledì 26 giugno 13
to make a single unit work
you often need other units
The problem is
mercoledì 26 giugno 13
provide canned answers to calls made during the
test, usually not responding at all to anything
outside what's programmed in for the test
Stub objects
mercoledì 26 giugno 13
objects pre-programmed with expectations
which form a specification of the calls
they are expected to receive
Mock objects
mercoledì 26 giugno 13
Mock objects
Behaviour
verification
State
verification
Stub objects
mercoledì 26 giugno 13
A simple stub example
public interface MailService {
public function send(Message $msg);
}
public class MailServiceStub implements MailService {
private $sent = 0;
public function send(Message $msg) {
/*I’m just sent the message */
++$sent;
}
public function numberSent() {
return $this->sent;
}
}
implementation
mercoledì 26 giugno 13
A simple stub example
state verification
class OrderStateTester{...
public function testOrderSendsMailIfFilled() {
$order = new Order(TALISKER, 51);
$mailer = new MailServiceStub();
$order->setMailer($mailer);
$order->fill(/*somestuff*/);
$this->assertEquals(1, $mailer->numberSent());
}
}
mercoledì 26 giugno 13
We’ve wrote a simple test.
We’ve tested only one message has been sent
BUT
We’ve not tested it was sent to the right
person with right content etc.
mercoledì 26 giugno 13
...using mock object
class OrderInteractionTester...
public function testOrderSendsMailIfFilled() {
$order = new Order(TALISKER, 51);
$warehouse = $this->mock(“Warehouse”);
$mailer = $this->mock(“MailService”);
$order->setMailer($mailer);
$mailer->expects(once())->method("send");
$warehouse->expects(once())->method("hasInventory")
->withAnyArguments()
->will(returnValue(false));
$order->fill($warehouse->proxy());
}
}
mercoledì 26 giugno 13
PHAKE
PHP MOCKING FRAMEWORK
mercoledì 26 giugno 13
Zero-config
Phake was designed with PHPUnit in mind
mercoledì 26 giugno 13
stub a method
$stub = $this->getMock('NamespaceMyClass');
$stub->expects($this->any())
->method('doSomething')
->with('param')
->will($this->returnValue('returned'));
with PHPUnit
mercoledì 26 giugno 13
stub a method
$stub = $this->getMock('NamespaceMyClass');
$stub->expects($this->any())
->method('doSomething')
->with('param')
->will($this->returnValue('returned'));
$stub = Phake::mock('NamespaceMyClass');
Phake::when($stub)->doSomething('param')->thenReturn('returned');
with PHPUnit
with Phake
mercoledì 26 giugno 13
an example
class ShoppingCartTest extends PHPUnit_Framework_TestCase
{
! private $shoppingCart;
! private $item1;
! private $item2;
! private $item3;
! public function setUp()
! {
! ! $this->item1 = Phake::mock('Item');
! ! $this->item2 = Phake::mock('Item');
! ! $this->item3 = Phake::mock('Item');
! ! Phake::when($this->item1)->getPrice()->thenReturn(100);
! ! Phake::when($this->item2)->getPrice()->thenReturn(200);
! ! Phake::when($this->item3)->getPrice()->thenReturn(300);
! ! $this->shoppingCart = new ShoppingCart();
! ! $this->shoppingCart->addItem($this->item1);
! ! $this->shoppingCart->addItem($this->item2);
! ! $this->shoppingCart->addItem($this->item3);
! }
! public function testGetSub()
! {
! ! $this->assertEquals(600, $this->shoppingCart->getSubTotal());
! }
}
mercoledì 26 giugno 13
ShoppingCart implementation
class ShoppingCart
{
! /**
! * Returns the current sub total of the customer's order
! * @return money
! */
! public function getSubTotal()
! {
! ! $total = 0;
! ! foreach ($this->items as $item)
! ! {
! ! ! $total += $item->getPrice();
! ! }
! ! return $total;
! }
}
mercoledì 26 giugno 13
stubbing multiple calls
$stub = $this->getMock('NamespaceMyClass');
$stub->expects($this->any())
->method('doSomething')
->will($this->returnCallback(function($param) {
$toReturn = array(
'param1' => 'returned1',
'param2' => 'returned2',
}));
with PHPUnit
mercoledì 26 giugno 13
stubbing multiple calls
$stub = $this->getMock('NamespaceMyClass');
$stub->expects($this->any())
->method('doSomething')
->will($this->returnCallback(function($param) {
$toReturn = array(
'param1' => 'returned1',
'param2' => 'returned2',
}));
$stub = Phake::mock('NamespaceMyClass');
Phake::when($stub)->doSomething('param1')->thenReturn('returned1')
Phake::when($stub)->doSomething('param2')->thenReturn('returned2');
with PHPUnit
with Phake
mercoledì 26 giugno 13
an example
class ItemGroupTest extends PHPUnit_Framework_TestCase
{
! private $itemGroup;
! private $item1;
! private $item2;
! private $item3;
! public function setUp()
! {
! ! $this->item1 = Phake::mock('Item');
! ! $this->item2 = Phake::mock('Item');
! ! $this->item3 = Phake::mock('Item');
! ! $this->itemGroup = new ItemGroup(array($this->item1, $this->item2, $this->item3));
! }
! public function testAddItemsToCart()
! {
! ! $cart = Phake::mock('ShoppingCart');
! ! Phake::when($cart)->addItem($this->item1)->thenReturn(10);
! ! Phake::when($cart)->addItem($this->item2)->thenReturn(20);
! ! Phake::when($cart)->addItem($this->item3)->thenReturn(30);
! ! $totalCost = $this->itemGroup->addItemsToCart($cart);
! ! $this->assertEquals(60, $totalCost);
! }
}
mercoledì 26 giugno 13
an example with consecutive calls
class ItemGroupTest extends PHPUnit_Framework_TestCase
{
! private $itemGroup;
! private $item1;
! private $item2;
! private $item3;
! public function setUp()
! {
! ! $this->item1 = Phake::mock('Item');
! ! $this->item2 = Phake::mock('Item');
! ! $this->item3 = Phake::mock('Item');
! ! $this->itemGroup = new ItemGroup(array($this->item1, $this->item2, $this->item3));
! }
! public function testAddItemsToCart()
! {
! ! $cart = Phake::mock('ShoppingCart');
! ! Phake::when($cart)->addItem(Phake::anyParameters())->thenReturn(10)
! ! ! ->thenReturn(20)
! ! ! ->thenReturn(30);
! ! $totalCost = $this->itemGroup->addItemsToCart($cart);
! ! $this->assertEquals(30, $totalCost);
! }
}
mercoledì 26 giugno 13
partial mock
class MyClass
{
! private $value;
! public __construct($value)
! {
! ! $this->value = $value;
! }
! public function foo()
! {
! ! return $this->value;
! }
}
mercoledì 26 giugno 13
partial mock
class MyClass
{
! private $value;
! public __construct($value)
! {
! ! $this->value = $value;
! }
! public function foo()
! {
! ! return $this->value;
! }
}
class MyClassTest extends PHPUnit_Framework_TestCase
{
! public function testCallingParent()
! {
! ! $mock = Phake::partialMock('MyClass', 42);
! ! $this->assertEquals(42, $mock->foo());
! }
}
mercoledì 26 giugno 13
default stub
class MyClassTest extends PHPUnit_Framework_TestCase
{
! public function testDefaultStubs()
! {
! ! $mock = Phake::mock('MyClass', Phake::ifUnstubbed()->thenReturn(42));
! ! $this->assertEquals(42, $mock->foo());
! }
}
class MyClass
{
! private $value;
! public __construct($value)
! {
! ! $this->value = $value;
! }
! public function foo()
! {
! ! return $this->value;
! }
}
mercoledì 26 giugno 13
stubbing magic methods
class MagicClass
{
public function __call($method, $args)
{
return '__call';
}
}
mercoledì 26 giugno 13
stubbing magic methods
class MagicClass
{
public function __call($method, $args)
{
return '__call';
}
}
class MagicClassTest extends PHPUnit_Framework_TestCase
{
public function testMagicCall()
{
$mock = Phake::mock('MagicClass');
Phake::when($mock)->myMethod()->thenReturn(42);
$this->assertEquals(42, $mock->myMethod());
}
}
MyMethod is handled by __call() method
mercoledì 26 giugno 13
verify invocations
class MyTest extends PHPUnit_Framework_TestCase
{
public function testPHPUnitMock()
{
$mock = $this->getMock('PhakeTest_MockedClass');
$mock->expects($this->once())->method('fooWithArgument')
->with('foo');
$mock->expects($this->once())->method('fooWithArgument')
->with('bar');
$mock->fooWithArgument('foo');
$mock->fooWithArgument('bar');
}
}
with PHPUnit - BAD!
mercoledì 26 giugno 13
verify invocations
class MyTest extends PHPUnit_Framework_TestCase
{
public function testPHPUnitMock()
{
$mock = $this->getMock('PhakeTest_MockedClass');
$mock->expects($this->once())->method('fooWithArgument')
->with('foo');
$mock->expects($this->once())->method('fooWithArgument')
->with('bar');
$mock->fooWithArgument('foo');
$mock->fooWithArgument('bar');
}
}
with PHPUnit - BAD!
//I’m failing, with you!
mercoledì 26 giugno 13
verify invocations
class MyTest extends PHPUnit_Framework_TestCase
{
public function testPHPUnitMock()
{
$mock = $this->getMock('PhakeTest_MockedClass');
$mock->expects($this->at(0))->method('fooWithArgument')
->with('foo');
$mock->expects($this->at(1))->method('fooWithArgument')
->with('bar');
$mock->fooWithArgument('foo');
$mock->fooWithArgument('bar');
}
}
with PHPUnit - BETTER
mercoledì 26 giugno 13
verify invocations
class MyTest extends PHPUnit_Framework_TestCase
{
public function testPHPUnitMock()
{
$mock = Phake::mock('PhakeTest_MockedClass');
$mock->fooWithArgument('foo');
$mock->fooWithArgument('bar');
Phake::verify($mock)->fooWithArgument('foo');
Phake::verify($mock)->fooWithArgument('bar');
}
}
with Phake
mercoledì 26 giugno 13
verify invocations
class MyTest extends PHPUnit_Framework_TestCase
{
public function testPHPUnitMock()
{
$mock = Phake::mock('PhakeTest_MockedClass');
$mock->fooWithArgument('foo');
$mock->fooWithArgument('foo');
Phake::verify($mock, Phake::times(2))->fooWithArgument('foo');
}
}
with Phake - multiple invocation
Phake::times($n)
Phake::atLeast($n)
Phake::atMost($n)
options:
mercoledì 26 giugno 13
verify invocations in order
class MyTest extends PHPUnit_Framework_TestCase
{
public function testPHPUnitMock()
{
$mock = Phake::mock('PhakeTest_MockedClass');
$mock->fooWithArgument('foo');
$mock->fooWithArgument('bar');
Phake::inOrder(
Phake::verify($mock)->fooWithArgument('foo'),
Phake::verify($mock)->fooWithArgument('bar')
);
}
}
mercoledì 26 giugno 13
verify no interaction
class MyTest extends PHPUnit_Framework_TestCase
{
public function testPHPUnitNoInteraction()
{
$mock = $this->getMock('PhakeTestCase_MockedClass');
$mock->expects($this->never())
->method('foo');
//....
}
}
with PHPUnit
mercoledì 26 giugno 13
verify no interaction
class MyTest extends PHPUnit_Framework_TestCase
{
public function testPHPUnitNoInteraction()
{
$mock = $this->getMock('PhakeTestCase_MockedClass');
$mock->expects($this->never())
->method('foo');
//....
}
}
with PHPUnit
class MyTest extends PHPUnit_Framework_TestCase
{
public function testPhakeNoInteraction()
{
$mock = Phake::mock('PhakeTestCase_MockedClass');
//...
Phake::verifyNoInteractions($mock);
}
}
with Phake
mercoledì 26 giugno 13
verify magic calls
class MagicClass
{
public function __call($method, $args)
{
return '__call';
}
}
mercoledì 26 giugno 13
verify magic calls
class MagicClass
{
public function __call($method, $args)
{
return '__call';
}
}
class MagicClassTest extends PHPUnit_Framework_TestCase
{
public function testMagicCall()
{
$mock = Phake::mock('MagicClass');
$mock->myMethod();
Phake::verify($mock)->myMethod();
}
}
mercoledì 26 giugno 13
throwing exception
class MyClass
{
! private $logger;
!
! public function __construct(Logger $logger)
! {
! ! $this->logger = $logger;
! }
! public function processSomeData(MyDataProcessor $processor, MyData $data)
! {
! ! try {
! ! ! $processor->process($data);
! ! }
! ! catch (Exception $e) {
! ! ! $this->logger->log($e->getMessage());
! ! }
! }
}
Suppose you have a class that logs a message with the exception message
mercoledì 26 giugno 13
throwing exception
class MyClassTest extends PHPUnit_Framework_TestCase
{
! public function testProcessSomeDataLogsExceptions()
! {
! ! $logger = Phake::mock('Logger');
! ! $data = Phake::mock('MyData');
! ! $processor = Phake::mock('MyDataProcessor');
! !
Suppose you have a class that logs a message with the exception message
mercoledì 26 giugno 13
throwing exception
class MyClassTest extends PHPUnit_Framework_TestCase
{
! public function testProcessSomeDataLogsExceptions()
! {
! ! $logger = Phake::mock('Logger');
! ! $data = Phake::mock('MyData');
! ! $processor = Phake::mock('MyDataProcessor');
! !
Suppose you have a class that logs a message with the exception message
! ! Phake::when($processor)->process($data)
->thenThrow(new Exception('My error message!');
mercoledì 26 giugno 13
throwing exception
class MyClassTest extends PHPUnit_Framework_TestCase
{
! public function testProcessSomeDataLogsExceptions()
! {
! ! $logger = Phake::mock('Logger');
! ! $data = Phake::mock('MyData');
! ! $processor = Phake::mock('MyDataProcessor');
! !
Suppose you have a class that logs a message with the exception message
! ! Phake::when($processor)->process($data)
->thenThrow(new Exception('My error message!');
! ! $sut = new MyClass($logger);
! ! $sut->processSomeData($processor, $data);
mercoledì 26 giugno 13
throwing exception
class MyClassTest extends PHPUnit_Framework_TestCase
{
! public function testProcessSomeDataLogsExceptions()
! {
! ! $logger = Phake::mock('Logger');
! ! $data = Phake::mock('MyData');
! ! $processor = Phake::mock('MyDataProcessor');
! !
Suppose you have a class that logs a message with the exception message
! ! Phake::when($processor)->process($data)
->thenThrow(new Exception('My error message!');
! ! $sut = new MyClass($logger);
! ! $sut->processSomeData($processor, $data);
! ! Phake::verify($logger)->log('My error message!');
! }
}
mercoledì 26 giugno 13
parameter capturing
interface CardCollection
{
public function getNumberOfCards();
}
class MyPokerGameTest extends PHPUnit_Framework_TestCase
{
public function testDealCards()
{
$dealer = Phake::partialMock('MyPokerDealer');
$players = Phake::mock('PlayerCollection');
$cardGame = new MyPokerGame($dealer, $players);
Phake::verify($dealer)->deal(Phake::capture($deck), $players);
$this->assertEquals(52, $deck->getNumberOfCards());
}
}
Class MyPokerDealer
{
public function getNumberOfCards(){
..
..
$dealer->deal($deck, $players)
}
}
mercoledì 26 giugno 13
Phake
pear channel-discover pear.digitalsandwich.com
pear install digitalsandwich/Phake
Available via pear
Available via Composer
"phake/phake": "dev-master"
mercoledì 26 giugno 13
Questions?
Thanks!
Andrea Giuliano
@bit_shark
mercoledì 26 giugno 13

Weitere ähnliche Inhalte

Was ist angesagt?

How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF Luc Bors
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologyDaniel Knell
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patternsSamuel ROZE
 
dcs plus Catalogue 2015
dcs plus Catalogue 2015dcs plus Catalogue 2015
dcs plus Catalogue 2015dcs plus
 
Class-based views with Django
Class-based views with DjangoClass-based views with Django
Class-based views with DjangoSimon Willison
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form componentSamuel ROZE
 
jQuery Namespace Pattern
jQuery Namespace PatternjQuery Namespace Pattern
jQuery Namespace PatternDiego Fleury
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in actionJace Ju
 
Feature flagsareflawed
Feature flagsareflawedFeature flagsareflawed
Feature flagsareflawedStephen Young
 
Modern JavaScript Engine Performance
Modern JavaScript Engine PerformanceModern JavaScript Engine Performance
Modern JavaScript Engine PerformanceCatalin Dumitru
 
Unit-Testing Bad-Practices by Example
Unit-Testing Bad-Practices by ExampleUnit-Testing Bad-Practices by Example
Unit-Testing Bad-Practices by ExampleBenjamin Eberlei
 
Bad test, good test
Bad test, good testBad test, good test
Bad test, good testSeb Rose
 
Feature Flags Are Flawed: Let's Make Them Better
Feature Flags Are Flawed: Let's Make Them BetterFeature Flags Are Flawed: Let's Make Them Better
Feature Flags Are Flawed: Let's Make Them BetterStephen Young
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介Jace Ju
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mockingKonstantin Kudryashov
 
Unittesting Bad-Practices by Example
Unittesting Bad-Practices by ExampleUnittesting Bad-Practices by Example
Unittesting Bad-Practices by ExampleBenjamin Eberlei
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Fabien Potencier
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownpartsBastian Feder
 
The Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 SeasonsThe Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 SeasonsBaruch Sadogursky
 

Was ist angesagt? (20)

How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
 
dcs plus Catalogue 2015
dcs plus Catalogue 2015dcs plus Catalogue 2015
dcs plus Catalogue 2015
 
Class-based views with Django
Class-based views with DjangoClass-based views with Django
Class-based views with Django
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form component
 
jQuery Namespace Pattern
jQuery Namespace PatternjQuery Namespace Pattern
jQuery Namespace Pattern
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Feature flagsareflawed
Feature flagsareflawedFeature flagsareflawed
Feature flagsareflawed
 
Modern JavaScript Engine Performance
Modern JavaScript Engine PerformanceModern JavaScript Engine Performance
Modern JavaScript Engine Performance
 
Unit-Testing Bad-Practices by Example
Unit-Testing Bad-Practices by ExampleUnit-Testing Bad-Practices by Example
Unit-Testing Bad-Practices by Example
 
Bad test, good test
Bad test, good testBad test, good test
Bad test, good test
 
Feature Flags Are Flawed: Let's Make Them Better
Feature Flags Are Flawed: Let's Make Them BetterFeature Flags Are Flawed: Let's Make Them Better
Feature Flags Are Flawed: Let's Make Them Better
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 
Unittesting Bad-Practices by Example
Unittesting Bad-Practices by ExampleUnittesting Bad-Practices by Example
Unittesting Bad-Practices by Example
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
 
The Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 SeasonsThe Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 Seasons
 

Andere mochten auch

PHP Unit-Testing With Doubles
PHP Unit-Testing With DoublesPHP Unit-Testing With Doubles
PHP Unit-Testing With DoublesMihail Irintchev
 
Advanced PHPUnit Testing
Advanced PHPUnit TestingAdvanced PHPUnit Testing
Advanced PHPUnit TestingMike Lively
 
Breve introducción a TDD con Phpunit
Breve introducción a TDD con PhpunitBreve introducción a TDD con Phpunit
Breve introducción a TDD con Phpunitmoisesgallego
 
How to test models using php unit testing framework?
How to test models using php unit testing framework?How to test models using php unit testing framework?
How to test models using php unit testing framework?satejsahu
 
Ioc & in direction
Ioc & in directionIoc & in direction
Ioc & in direction育汶 郭
 
2007 5 30 肖镜辉 统计语言模型简介
2007 5 30 肖镜辉 统计语言模型简介2007 5 30 肖镜辉 统计语言模型简介
2007 5 30 肖镜辉 统计语言模型简介xceman
 
PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにYuya Takeyama
 
PHPUnit 入門介紹
PHPUnit 入門介紹PHPUnit 入門介紹
PHPUnit 入門介紹Jace Ju
 
PHPUnit best practices presentation
PHPUnit best practices presentationPHPUnit best practices presentation
PHPUnit best practices presentationThanh Robi
 
Introduction to Unit Testing with PHPUnit
Introduction to Unit Testing with PHPUnitIntroduction to Unit Testing with PHPUnit
Introduction to Unit Testing with PHPUnitMichelangelo van Dam
 
Jmeter Performance Testing
Jmeter Performance TestingJmeter Performance Testing
Jmeter Performance TestingAtul Pant
 
B M Social Media Fortune 100
B M Social Media Fortune 100B M Social Media Fortune 100
B M Social Media Fortune 100Burson-Marsteller
 
Di – ioc (ninject)
Di – ioc (ninject)Di – ioc (ninject)
Di – ioc (ninject)ZealousysDev
 

Andere mochten auch (15)

PHP Unit-Testing With Doubles
PHP Unit-Testing With DoublesPHP Unit-Testing With Doubles
PHP Unit-Testing With Doubles
 
Advanced PHPUnit Testing
Advanced PHPUnit TestingAdvanced PHPUnit Testing
Advanced PHPUnit Testing
 
Breve introducción a TDD con Phpunit
Breve introducción a TDD con PhpunitBreve introducción a TDD con Phpunit
Breve introducción a TDD con Phpunit
 
How to test models using php unit testing framework?
How to test models using php unit testing framework?How to test models using php unit testing framework?
How to test models using php unit testing framework?
 
Ioc & in direction
Ioc & in directionIoc & in direction
Ioc & in direction
 
IoC with PHP
IoC with PHPIoC with PHP
IoC with PHP
 
2007 5 30 肖镜辉 统计语言模型简介
2007 5 30 肖镜辉 统计语言模型简介2007 5 30 肖镜辉 统计语言模型简介
2007 5 30 肖镜辉 统计语言模型简介
 
PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くために
 
TDD Course (Spanish)
TDD Course (Spanish)TDD Course (Spanish)
TDD Course (Spanish)
 
PHPUnit 入門介紹
PHPUnit 入門介紹PHPUnit 入門介紹
PHPUnit 入門介紹
 
PHPUnit best practices presentation
PHPUnit best practices presentationPHPUnit best practices presentation
PHPUnit best practices presentation
 
Introduction to Unit Testing with PHPUnit
Introduction to Unit Testing with PHPUnitIntroduction to Unit Testing with PHPUnit
Introduction to Unit Testing with PHPUnit
 
Jmeter Performance Testing
Jmeter Performance TestingJmeter Performance Testing
Jmeter Performance Testing
 
B M Social Media Fortune 100
B M Social Media Fortune 100B M Social Media Fortune 100
B M Social Media Fortune 100
 
Di – ioc (ninject)
Di – ioc (ninject)Di – ioc (ninject)
Di – ioc (ninject)
 

Ähnlich wie Stub you!

Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitmfrost503
 
Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitmfrost503
 
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnitinternational PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnitsmueller_sandsmedia
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsBastian Feder
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownpartsBastian Feder
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutesBarang CK
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 MinutesAzim Kurt
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosDivante
 
Symfony (Unit, Functional) Testing.
Symfony (Unit, Functional) Testing.Symfony (Unit, Functional) Testing.
Symfony (Unit, Functional) Testing.Basel Issmail
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ EtsyNishan Subedi
 
Pim Elshoff "Technically DDD"
Pim Elshoff "Technically DDD"Pim Elshoff "Technically DDD"
Pim Elshoff "Technically DDD"Fwdays
 
Introducing CakeEntity
Introducing CakeEntityIntroducing CakeEntity
Introducing CakeEntityBasuke Suzuki
 

Ähnlich wie Stub you! (20)

Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnit
 
Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnit
 
PHP Unit Testing
PHP Unit TestingPHP Unit Testing
PHP Unit Testing
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
Workshop unittesting
Workshop unittestingWorkshop unittesting
Workshop unittesting
 
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnitinternational PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
 
Software Testing
Software TestingSoftware Testing
Software Testing
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
 
Wp query
Wp queryWp query
Wp query
 
Test driven development_for_php
Test driven development_for_phpTest driven development_for_php
Test driven development_for_php
 
Oops in php
Oops in phpOops in php
Oops in php
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutes
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes
 
jQuery secrets
jQuery secretsjQuery secrets
jQuery secrets
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 
Symfony (Unit, Functional) Testing.
Symfony (Unit, Functional) Testing.Symfony (Unit, Functional) Testing.
Symfony (Unit, Functional) Testing.
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ Etsy
 
Pim Elshoff "Technically DDD"
Pim Elshoff "Technically DDD"Pim Elshoff "Technically DDD"
Pim Elshoff "Technically DDD"
 
Introducing CakeEntity
Introducing CakeEntityIntroducing CakeEntity
Introducing CakeEntity
 

Mehr von Andrea Giuliano

CQRS, ReactJS, Docker in a nutshell
CQRS, ReactJS, Docker in a nutshellCQRS, ReactJS, Docker in a nutshell
CQRS, ReactJS, Docker in a nutshellAndrea Giuliano
 
Go fast in a graph world
Go fast in a graph worldGo fast in a graph world
Go fast in a graph worldAndrea Giuliano
 
Concurrent test frameworks
Concurrent test frameworksConcurrent test frameworks
Concurrent test frameworksAndrea Giuliano
 
Index management in depth
Index management in depthIndex management in depth
Index management in depthAndrea Giuliano
 
Consistency, Availability, Partition: Make Your Choice
Consistency, Availability, Partition: Make Your ChoiceConsistency, Availability, Partition: Make Your Choice
Consistency, Availability, Partition: Make Your ChoiceAndrea Giuliano
 
Asynchronous data processing
Asynchronous data processingAsynchronous data processing
Asynchronous data processingAndrea Giuliano
 
Think horizontally @Codemotion
Think horizontally @CodemotionThink horizontally @Codemotion
Think horizontally @CodemotionAndrea Giuliano
 
Index management in shallow depth
Index management in shallow depthIndex management in shallow depth
Index management in shallow depthAndrea Giuliano
 
Everything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to askEverything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to askAndrea Giuliano
 

Mehr von Andrea Giuliano (10)

CQRS, ReactJS, Docker in a nutshell
CQRS, ReactJS, Docker in a nutshellCQRS, ReactJS, Docker in a nutshell
CQRS, ReactJS, Docker in a nutshell
 
Go fast in a graph world
Go fast in a graph worldGo fast in a graph world
Go fast in a graph world
 
Concurrent test frameworks
Concurrent test frameworksConcurrent test frameworks
Concurrent test frameworks
 
Index management in depth
Index management in depthIndex management in depth
Index management in depth
 
Consistency, Availability, Partition: Make Your Choice
Consistency, Availability, Partition: Make Your ChoiceConsistency, Availability, Partition: Make Your Choice
Consistency, Availability, Partition: Make Your Choice
 
Asynchronous data processing
Asynchronous data processingAsynchronous data processing
Asynchronous data processing
 
Think horizontally @Codemotion
Think horizontally @CodemotionThink horizontally @Codemotion
Think horizontally @Codemotion
 
Index management in shallow depth
Index management in shallow depthIndex management in shallow depth
Index management in shallow depth
 
Everything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to askEverything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to ask
 
Let's test!
Let's test!Let's test!
Let's test!
 

Kürzlich hochgeladen

Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 

Kürzlich hochgeladen (20)

Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 

Stub you!

  • 2. When you’re doing testing you’re focusing on one element at a time Unit testing mercoledì 26 giugno 13
  • 3. to make a single unit work you often need other units The problem is mercoledì 26 giugno 13
  • 4. provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test Stub objects mercoledì 26 giugno 13
  • 5. objects pre-programmed with expectations which form a specification of the calls they are expected to receive Mock objects mercoledì 26 giugno 13
  • 7. A simple stub example public interface MailService { public function send(Message $msg); } public class MailServiceStub implements MailService { private $sent = 0; public function send(Message $msg) { /*I’m just sent the message */ ++$sent; } public function numberSent() { return $this->sent; } } implementation mercoledì 26 giugno 13
  • 8. A simple stub example state verification class OrderStateTester{... public function testOrderSendsMailIfFilled() { $order = new Order(TALISKER, 51); $mailer = new MailServiceStub(); $order->setMailer($mailer); $order->fill(/*somestuff*/); $this->assertEquals(1, $mailer->numberSent()); } } mercoledì 26 giugno 13
  • 9. We’ve wrote a simple test. We’ve tested only one message has been sent BUT We’ve not tested it was sent to the right person with right content etc. mercoledì 26 giugno 13
  • 10. ...using mock object class OrderInteractionTester... public function testOrderSendsMailIfFilled() { $order = new Order(TALISKER, 51); $warehouse = $this->mock(“Warehouse”); $mailer = $this->mock(“MailService”); $order->setMailer($mailer); $mailer->expects(once())->method("send"); $warehouse->expects(once())->method("hasInventory") ->withAnyArguments() ->will(returnValue(false)); $order->fill($warehouse->proxy()); } } mercoledì 26 giugno 13
  • 12. Zero-config Phake was designed with PHPUnit in mind mercoledì 26 giugno 13
  • 13. stub a method $stub = $this->getMock('NamespaceMyClass'); $stub->expects($this->any()) ->method('doSomething') ->with('param') ->will($this->returnValue('returned')); with PHPUnit mercoledì 26 giugno 13
  • 14. stub a method $stub = $this->getMock('NamespaceMyClass'); $stub->expects($this->any()) ->method('doSomething') ->with('param') ->will($this->returnValue('returned')); $stub = Phake::mock('NamespaceMyClass'); Phake::when($stub)->doSomething('param')->thenReturn('returned'); with PHPUnit with Phake mercoledì 26 giugno 13
  • 15. an example class ShoppingCartTest extends PHPUnit_Framework_TestCase { ! private $shoppingCart; ! private $item1; ! private $item2; ! private $item3; ! public function setUp() ! { ! ! $this->item1 = Phake::mock('Item'); ! ! $this->item2 = Phake::mock('Item'); ! ! $this->item3 = Phake::mock('Item'); ! ! Phake::when($this->item1)->getPrice()->thenReturn(100); ! ! Phake::when($this->item2)->getPrice()->thenReturn(200); ! ! Phake::when($this->item3)->getPrice()->thenReturn(300); ! ! $this->shoppingCart = new ShoppingCart(); ! ! $this->shoppingCart->addItem($this->item1); ! ! $this->shoppingCart->addItem($this->item2); ! ! $this->shoppingCart->addItem($this->item3); ! } ! public function testGetSub() ! { ! ! $this->assertEquals(600, $this->shoppingCart->getSubTotal()); ! } } mercoledì 26 giugno 13
  • 16. ShoppingCart implementation class ShoppingCart { ! /** ! * Returns the current sub total of the customer's order ! * @return money ! */ ! public function getSubTotal() ! { ! ! $total = 0; ! ! foreach ($this->items as $item) ! ! { ! ! ! $total += $item->getPrice(); ! ! } ! ! return $total; ! } } mercoledì 26 giugno 13
  • 17. stubbing multiple calls $stub = $this->getMock('NamespaceMyClass'); $stub->expects($this->any()) ->method('doSomething') ->will($this->returnCallback(function($param) { $toReturn = array( 'param1' => 'returned1', 'param2' => 'returned2', })); with PHPUnit mercoledì 26 giugno 13
  • 18. stubbing multiple calls $stub = $this->getMock('NamespaceMyClass'); $stub->expects($this->any()) ->method('doSomething') ->will($this->returnCallback(function($param) { $toReturn = array( 'param1' => 'returned1', 'param2' => 'returned2', })); $stub = Phake::mock('NamespaceMyClass'); Phake::when($stub)->doSomething('param1')->thenReturn('returned1') Phake::when($stub)->doSomething('param2')->thenReturn('returned2'); with PHPUnit with Phake mercoledì 26 giugno 13
  • 19. an example class ItemGroupTest extends PHPUnit_Framework_TestCase { ! private $itemGroup; ! private $item1; ! private $item2; ! private $item3; ! public function setUp() ! { ! ! $this->item1 = Phake::mock('Item'); ! ! $this->item2 = Phake::mock('Item'); ! ! $this->item3 = Phake::mock('Item'); ! ! $this->itemGroup = new ItemGroup(array($this->item1, $this->item2, $this->item3)); ! } ! public function testAddItemsToCart() ! { ! ! $cart = Phake::mock('ShoppingCart'); ! ! Phake::when($cart)->addItem($this->item1)->thenReturn(10); ! ! Phake::when($cart)->addItem($this->item2)->thenReturn(20); ! ! Phake::when($cart)->addItem($this->item3)->thenReturn(30); ! ! $totalCost = $this->itemGroup->addItemsToCart($cart); ! ! $this->assertEquals(60, $totalCost); ! } } mercoledì 26 giugno 13
  • 20. an example with consecutive calls class ItemGroupTest extends PHPUnit_Framework_TestCase { ! private $itemGroup; ! private $item1; ! private $item2; ! private $item3; ! public function setUp() ! { ! ! $this->item1 = Phake::mock('Item'); ! ! $this->item2 = Phake::mock('Item'); ! ! $this->item3 = Phake::mock('Item'); ! ! $this->itemGroup = new ItemGroup(array($this->item1, $this->item2, $this->item3)); ! } ! public function testAddItemsToCart() ! { ! ! $cart = Phake::mock('ShoppingCart'); ! ! Phake::when($cart)->addItem(Phake::anyParameters())->thenReturn(10) ! ! ! ->thenReturn(20) ! ! ! ->thenReturn(30); ! ! $totalCost = $this->itemGroup->addItemsToCart($cart); ! ! $this->assertEquals(30, $totalCost); ! } } mercoledì 26 giugno 13
  • 21. partial mock class MyClass { ! private $value; ! public __construct($value) ! { ! ! $this->value = $value; ! } ! public function foo() ! { ! ! return $this->value; ! } } mercoledì 26 giugno 13
  • 22. partial mock class MyClass { ! private $value; ! public __construct($value) ! { ! ! $this->value = $value; ! } ! public function foo() ! { ! ! return $this->value; ! } } class MyClassTest extends PHPUnit_Framework_TestCase { ! public function testCallingParent() ! { ! ! $mock = Phake::partialMock('MyClass', 42); ! ! $this->assertEquals(42, $mock->foo()); ! } } mercoledì 26 giugno 13
  • 23. default stub class MyClassTest extends PHPUnit_Framework_TestCase { ! public function testDefaultStubs() ! { ! ! $mock = Phake::mock('MyClass', Phake::ifUnstubbed()->thenReturn(42)); ! ! $this->assertEquals(42, $mock->foo()); ! } } class MyClass { ! private $value; ! public __construct($value) ! { ! ! $this->value = $value; ! } ! public function foo() ! { ! ! return $this->value; ! } } mercoledì 26 giugno 13
  • 24. stubbing magic methods class MagicClass { public function __call($method, $args) { return '__call'; } } mercoledì 26 giugno 13
  • 25. stubbing magic methods class MagicClass { public function __call($method, $args) { return '__call'; } } class MagicClassTest extends PHPUnit_Framework_TestCase { public function testMagicCall() { $mock = Phake::mock('MagicClass'); Phake::when($mock)->myMethod()->thenReturn(42); $this->assertEquals(42, $mock->myMethod()); } } MyMethod is handled by __call() method mercoledì 26 giugno 13
  • 26. verify invocations class MyTest extends PHPUnit_Framework_TestCase { public function testPHPUnitMock() { $mock = $this->getMock('PhakeTest_MockedClass'); $mock->expects($this->once())->method('fooWithArgument') ->with('foo'); $mock->expects($this->once())->method('fooWithArgument') ->with('bar'); $mock->fooWithArgument('foo'); $mock->fooWithArgument('bar'); } } with PHPUnit - BAD! mercoledì 26 giugno 13
  • 27. verify invocations class MyTest extends PHPUnit_Framework_TestCase { public function testPHPUnitMock() { $mock = $this->getMock('PhakeTest_MockedClass'); $mock->expects($this->once())->method('fooWithArgument') ->with('foo'); $mock->expects($this->once())->method('fooWithArgument') ->with('bar'); $mock->fooWithArgument('foo'); $mock->fooWithArgument('bar'); } } with PHPUnit - BAD! //I’m failing, with you! mercoledì 26 giugno 13
  • 28. verify invocations class MyTest extends PHPUnit_Framework_TestCase { public function testPHPUnitMock() { $mock = $this->getMock('PhakeTest_MockedClass'); $mock->expects($this->at(0))->method('fooWithArgument') ->with('foo'); $mock->expects($this->at(1))->method('fooWithArgument') ->with('bar'); $mock->fooWithArgument('foo'); $mock->fooWithArgument('bar'); } } with PHPUnit - BETTER mercoledì 26 giugno 13
  • 29. verify invocations class MyTest extends PHPUnit_Framework_TestCase { public function testPHPUnitMock() { $mock = Phake::mock('PhakeTest_MockedClass'); $mock->fooWithArgument('foo'); $mock->fooWithArgument('bar'); Phake::verify($mock)->fooWithArgument('foo'); Phake::verify($mock)->fooWithArgument('bar'); } } with Phake mercoledì 26 giugno 13
  • 30. verify invocations class MyTest extends PHPUnit_Framework_TestCase { public function testPHPUnitMock() { $mock = Phake::mock('PhakeTest_MockedClass'); $mock->fooWithArgument('foo'); $mock->fooWithArgument('foo'); Phake::verify($mock, Phake::times(2))->fooWithArgument('foo'); } } with Phake - multiple invocation Phake::times($n) Phake::atLeast($n) Phake::atMost($n) options: mercoledì 26 giugno 13
  • 31. verify invocations in order class MyTest extends PHPUnit_Framework_TestCase { public function testPHPUnitMock() { $mock = Phake::mock('PhakeTest_MockedClass'); $mock->fooWithArgument('foo'); $mock->fooWithArgument('bar'); Phake::inOrder( Phake::verify($mock)->fooWithArgument('foo'), Phake::verify($mock)->fooWithArgument('bar') ); } } mercoledì 26 giugno 13
  • 32. verify no interaction class MyTest extends PHPUnit_Framework_TestCase { public function testPHPUnitNoInteraction() { $mock = $this->getMock('PhakeTestCase_MockedClass'); $mock->expects($this->never()) ->method('foo'); //.... } } with PHPUnit mercoledì 26 giugno 13
  • 33. verify no interaction class MyTest extends PHPUnit_Framework_TestCase { public function testPHPUnitNoInteraction() { $mock = $this->getMock('PhakeTestCase_MockedClass'); $mock->expects($this->never()) ->method('foo'); //.... } } with PHPUnit class MyTest extends PHPUnit_Framework_TestCase { public function testPhakeNoInteraction() { $mock = Phake::mock('PhakeTestCase_MockedClass'); //... Phake::verifyNoInteractions($mock); } } with Phake mercoledì 26 giugno 13
  • 34. verify magic calls class MagicClass { public function __call($method, $args) { return '__call'; } } mercoledì 26 giugno 13
  • 35. verify magic calls class MagicClass { public function __call($method, $args) { return '__call'; } } class MagicClassTest extends PHPUnit_Framework_TestCase { public function testMagicCall() { $mock = Phake::mock('MagicClass'); $mock->myMethod(); Phake::verify($mock)->myMethod(); } } mercoledì 26 giugno 13
  • 36. throwing exception class MyClass { ! private $logger; ! ! public function __construct(Logger $logger) ! { ! ! $this->logger = $logger; ! } ! public function processSomeData(MyDataProcessor $processor, MyData $data) ! { ! ! try { ! ! ! $processor->process($data); ! ! } ! ! catch (Exception $e) { ! ! ! $this->logger->log($e->getMessage()); ! ! } ! } } Suppose you have a class that logs a message with the exception message mercoledì 26 giugno 13
  • 37. throwing exception class MyClassTest extends PHPUnit_Framework_TestCase { ! public function testProcessSomeDataLogsExceptions() ! { ! ! $logger = Phake::mock('Logger'); ! ! $data = Phake::mock('MyData'); ! ! $processor = Phake::mock('MyDataProcessor'); ! ! Suppose you have a class that logs a message with the exception message mercoledì 26 giugno 13
  • 38. throwing exception class MyClassTest extends PHPUnit_Framework_TestCase { ! public function testProcessSomeDataLogsExceptions() ! { ! ! $logger = Phake::mock('Logger'); ! ! $data = Phake::mock('MyData'); ! ! $processor = Phake::mock('MyDataProcessor'); ! ! Suppose you have a class that logs a message with the exception message ! ! Phake::when($processor)->process($data) ->thenThrow(new Exception('My error message!'); mercoledì 26 giugno 13
  • 39. throwing exception class MyClassTest extends PHPUnit_Framework_TestCase { ! public function testProcessSomeDataLogsExceptions() ! { ! ! $logger = Phake::mock('Logger'); ! ! $data = Phake::mock('MyData'); ! ! $processor = Phake::mock('MyDataProcessor'); ! ! Suppose you have a class that logs a message with the exception message ! ! Phake::when($processor)->process($data) ->thenThrow(new Exception('My error message!'); ! ! $sut = new MyClass($logger); ! ! $sut->processSomeData($processor, $data); mercoledì 26 giugno 13
  • 40. throwing exception class MyClassTest extends PHPUnit_Framework_TestCase { ! public function testProcessSomeDataLogsExceptions() ! { ! ! $logger = Phake::mock('Logger'); ! ! $data = Phake::mock('MyData'); ! ! $processor = Phake::mock('MyDataProcessor'); ! ! Suppose you have a class that logs a message with the exception message ! ! Phake::when($processor)->process($data) ->thenThrow(new Exception('My error message!'); ! ! $sut = new MyClass($logger); ! ! $sut->processSomeData($processor, $data); ! ! Phake::verify($logger)->log('My error message!'); ! } } mercoledì 26 giugno 13
  • 41. parameter capturing interface CardCollection { public function getNumberOfCards(); } class MyPokerGameTest extends PHPUnit_Framework_TestCase { public function testDealCards() { $dealer = Phake::partialMock('MyPokerDealer'); $players = Phake::mock('PlayerCollection'); $cardGame = new MyPokerGame($dealer, $players); Phake::verify($dealer)->deal(Phake::capture($deck), $players); $this->assertEquals(52, $deck->getNumberOfCards()); } } Class MyPokerDealer { public function getNumberOfCards(){ .. .. $dealer->deal($deck, $players) } } mercoledì 26 giugno 13
  • 42. Phake pear channel-discover pear.digitalsandwich.com pear install digitalsandwich/Phake Available via pear Available via Composer "phake/phake": "dev-master" mercoledì 26 giugno 13