SlideShare una empresa de Scribd logo
1 de 43
Descargar para leer sin conexión
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

Más contenido relacionado

La actualidad más candente

Modern JavaScript Engine Performance
Modern JavaScript Engine PerformanceModern JavaScript Engine Performance
Modern JavaScript Engine Performance
Catalin Dumitru
 
Unit-Testing Bad-Practices by Example
Unit-Testing Bad-Practices by ExampleUnit-Testing Bad-Practices by Example
Unit-Testing Bad-Practices by Example
Benjamin Eberlei
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)
Fabien Potencier
 

La actualidad más candente (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
 

Destacado

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
moisesgallego
 
Jmeter Performance Testing
Jmeter Performance TestingJmeter Performance Testing
Jmeter Performance Testing
Atul Pant
 

Destacado (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)
 

Similar a Stub you!

Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnit
mfrost503
 
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
smueller_sandsmedia
 

Similar a 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
 

Más de Andrea Giuliano

Más 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!
 

Último

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Último (20)

Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
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...
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
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
 
[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
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
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
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
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...
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 

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