SlideShare une entreprise Scribd logo
1  sur  43
Télécharger pour lire hors ligne
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

Contenu connexe

Tendances

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
 

Tendances (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
 

En vedette

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
 

En vedette (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)
 

Similaire à 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
 

Similaire à 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
 

Plus de 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
 

Plus de 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!
 

Dernier

Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 

Dernier (20)

Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 

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