Test in Action – Week 3      Stub / Mock      Hubert Chan
Back to Basics• Wikipedia said unit testing is  – A software verification and validation method in    which a programmer t...
Dependency in the Test• System Under Test (SUT) Dependency  – SUT need another module to perform its task     • Handler ne...
Real Object is Hard to Test• Real object  – Supplies non-deterministic results     • (e.g. the current temperature)  – Dif...
Substitute Dependency• Using Fake  – Fake is anything not real• Fake techniques  – Mock object  – Stub object  – Fake object
Stub Objects• Stub Objects  – Stubs provide canned answers to calls made    during the test  – Usually not responding at a...
Fake Objects• Fake Objects  – Fake objects have working implementations  – Usually take some shortcut, which makes them   ...
Example: AlertSystem
Example: AlertSystem• Component Overview  – AlertSystem     • Send notification to the targets, such as e-mail or SMS     ...
AlertSystem Test• Dependency Analysis  – Collaboration Classes     • NotifierInterface     • NotifierTargetProviderInterfa...
Make a Fake?• FileNotifyTargetProviderclass FileNotifyTargetProvider    implements NotifyTargetProviderInterface {    func...
Make a Stub?• StubNotifierclass StubNotifier implements NotifierInterface {    public function notify($target, $content) {...
Example: Test Code• Test Codeclass AlertSystemTest extends PHPUnit_Framework_TestCase {    public function test_sendNotify...
Manual Fake or Stub• Pros  – Fake or stub can be used as library  – Shared implementation• Cons  – Different scenarios nee...
Manual Stub or Fake• Cons  – Need extra efforts/logics for behaviors     • Setting return value     • Setting thrown excep...
Test Doubles• Using manual stub and mock  – Is $notifier->notify() be called?  – Does the target of $notifier->notify equa...
Mock objects• Mock Objects  – Mocks are objects pre-programmed with    expectations, which form a specification of the    ...
Mock Object Example• Mock Object Example public function test_sendNotify_Mock_NoException() {     $notify_content = fake_c...
Mock Object Example• Mock Object Verification  – $notifier->notify is called only once  – $notifier->notify 1st parameter ...
Using PHPUnit Stub• Return Valuepublic function test_sendNotify_Mock_NoException() {    $stub_provider = $this->getMock(No...
Using PHPUnit Stub• Return one of the argumentspublic function testReturnArgumentStub() {  // Create a stub for the SomeCl...
Using PHPUnit Stub• Return a value from a callback     – Useful for “out” parameterpublic function testReturnCallbackStub(...
PHPUnit Stub• Throw Exceptionpublic function testThrowExceptionStub() {  // Create a stub for the SomeClass class.  $stub ...
Misconception About Mocks• Mocks are just Stubs  – Mock is behavior verification     • Is the function called?     • Is th...
Is it HARD to use stub/mock?• Untestable code  – Make Your Own Dependencies  – Heavy Duty Constructors  – Depend on Concre...
Dependency Injection• Without dependency injection  – Use “new” operator inside your class  – Make mock object injection d...
AlertSystem again• AlertSystem (Hard to Test)     – Concrete classes     – Make Your Own Dependencies class AlertSystem { ...
AlertSystem constructor injection• Constructor Injectionclass AlertSystem {     protected $_notifier;     protected $_targ...
Not only for testing• Single Responsibility Principle  – Should alert system holds notifier and data    provider logic?  –...
The Law of Demeter• Definition  – Each unit should have only limited knowledge    about other units: only units "closely" ...
Violation of the Law• How do you test for?  – Mock for mock object, for another mock object  – Like Looking for a Needle i...
Law of Demeter - Explicit• Explicit   – We should not need to know the details of     collaborators    class Mechanic {   ...
Guide – Write Testable Code• Bad smell for non-testable Code  – Constructor does real work  – Digging into collaborators  ...
Conclusion• Writing good unit tests is hard• Good OO design brings good testability• Using stub/mock from mocking framework
Q&A
PHPUnit Log File• Junit Format<testsuites>  <testsuite name="AlertSystemTest"file="/usr/home/hubert/own/work/trend/process...
PHPUnit Coverage• PHPUnit Coverage  – Need Xdebug  – HTML format
Upcoming SlideShare
Loading in...5
×

Test in action week 3

1,591

Published on

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,591
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
7
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide
  • http://misko.hevery.com/2008/07/24/how-to-write-3v1l-untestable-code/
  • http://tutorials.jenkov.com/dependency-injection/index.html
  • https://secure.wikimedia.org/wikipedia/en/wiki/Law_of_Demeter
  • Test in action week 3

    1. 1. Test in Action – Week 3 Stub / Mock Hubert Chan
    2. 2. Back to Basics• Wikipedia said unit testing is – A software verification and validation method in which a programmer tests if individual units of source code are fit for use.
    3. 3. Dependency in the Test• System Under Test (SUT) Dependency – SUT need another module to perform its task • Handler need a $dbmodel to perform query • $handler = new Handler($dbmodel);
    4. 4. Real Object is Hard to Test• Real object – Supplies non-deterministic results • (e.g. the current temperature) – Difficult to create or reproduce (e.g. network fail) – Slow (e.g. database) – Does not yet exist or may change behavior
    5. 5. Substitute Dependency• Using Fake – Fake is anything not real• Fake techniques – Mock object – Stub object – Fake object
    6. 6. Stub Objects• Stub Objects – Stubs provide canned answers to calls made during the test – Usually not responding at all to anything outside whats programmed in for the test
    7. 7. Fake Objects• Fake Objects – Fake objects have working implementations – Usually take some shortcut, which makes them not suitable for production. – Example • An in-memory file system • An in-memory registry manager
    8. 8. Example: AlertSystem
    9. 9. Example: AlertSystem• Component Overview – AlertSystem • Send notification to the targets, such as e-mail or SMS notifier. – NotifierInterface instance • Send actually notification to the target – NotifierTargetProviderInterface instance • Provide a target array to send notification
    10. 10. AlertSystem Test• Dependency Analysis – Collaboration Classes • NotifierInterface • NotifierTargetProviderInterface• Tests should – Only focus on AlertSystem – Fake the dependency
    11. 11. Make a Fake?• FileNotifyTargetProviderclass FileNotifyTargetProvider implements NotifyTargetProviderInterface { function __construct($filename) { $this->_filename = $filename; } public function get_targets() { $targets = array(); $handle = @fopen($this->_filename, "r"); while (($target = fgets($handle)) !== FALSE) { $targets[] = $target; } return $targets; }}
    12. 12. Make a Stub?• StubNotifierclass StubNotifier implements NotifierInterface { public function notify($target, $content) { }}
    13. 13. Example: Test Code• Test Codeclass AlertSystemTest extends PHPUnit_Framework_TestCase { public function test_sendNotify_FakeNStub_NoException() { $target_file = __DIR__ . /data/targets.txt; $notifier = new StubNotifier(); $provider = new FileNotifyTargetProvider($target_file); $alert_system = new AlertSystem( $notifier, $provider ); $alert_system->send_notify(Alert!!); }}
    14. 14. Manual Fake or Stub• Pros – Fake or stub can be used as library – Shared implementation• Cons – Different scenarios need different implementation – Testing class explosion
    15. 15. Manual Stub or Fake• Cons – Need extra efforts/logics for behaviors • Setting return value • Setting thrown exception – Hard to validate • Calling sequence of functions • Passing arguments for functions • The method should be called
    16. 16. Test Doubles• Using manual stub and mock – Is $notifier->notify() be called? – Does the target of $notifier->notify equal to expect target? – Does the content of $notifier->notify equal to expect target?
    17. 17. Mock objects• Mock Objects – Mocks are objects pre-programmed with expectations, which form a specification of the calls they are expected to receive.
    18. 18. Mock Object Example• Mock Object Example public function test_sendNotify_Mock_NoException() { $notify_content = fake_content; $mock_notifier = $this->getMock(NotifierInterface); $mock_notifier->expects($this->once()) ->method(notify) ->with($this->anything(), $this->equalTo($notify_content)); $alert_system = new AlertSystem( $mock_notifier, $stub_provider ); $alert_system->send_notify(Alert!!); }
    19. 19. Mock Object Example• Mock Object Verification – $notifier->notify is called only once – $notifier->notify 1st parameter can be anything – $notifier->notify 2nd parameter should be equal to $notify_content
    20. 20. Using PHPUnit Stub• Return Valuepublic function test_sendNotify_Mock_NoException() { $stub_provider = $this->getMock(NotifyTargetProviderInterface); $targets = array(hubert); $stub_provider->expects($this->any()) ->method(get_targets) ->will($this->returnValue($targets)); $alert_system = new AlertSystem( $mock_notifier, $stub_provider ); $alert_system->send_notify(Alert!!);}
    21. 21. Using PHPUnit Stub• Return one of the argumentspublic function testReturnArgumentStub() { // Create a stub for the SomeClass class. $stub = $this->getMock(SomeClass); // Configure the stub. $stub->expects($this->any()) ->method(doSomething) ->will($this->returnArgument(0)); // $stub->doSomething(foo) returns foo $this->assertEquals(foo, $stub->doSomething(foo)); // $stub->doSomething(bar) returns bar $this->assertEquals(bar, $stub->doSomething(bar));}
    22. 22. Using PHPUnit Stub• Return a value from a callback – Useful for “out” parameterpublic function testReturnCallbackStub() { // Create a stub for the SomeClass class. $stub = $this->getMock(SomeClass); // Configure the stub. $stub->expects($this->any()) ->method(doSomething) ->will($this->returnCallback(str_rot13)); // $stub->doSomething($argument) returns str_rot13($argument) $this->assertEquals(fbzrguvat, $stub->doSomething(something));}
    23. 23. PHPUnit Stub• Throw Exceptionpublic function testThrowExceptionStub() { // Create a stub for the SomeClass class. $stub = $this->getMock(SomeClass); // Configure the stub. $stub->expects($this->any()) ->method(doSomething) ->will($this->throwException(new Exception)); // $stub->doSomething() throws Exception $stub->doSomething();}
    24. 24. Misconception About Mocks• Mocks are just Stubs – Mock is behavior verification • Is the function called? • Is the parameter passed correctly? – Stub is used for state verification – References • Mocks Aren’t Stubs – http://martinfowler.com/articles/mocksArentStubs.html
    25. 25. Is it HARD to use stub/mock?• Untestable code – Make Your Own Dependencies – Heavy Duty Constructors – Depend on Concrete Classes – Use Statics – Using Singleton Everywhere – Look for Everything You Need
    26. 26. Dependency Injection• Without dependency injection – Use “new” operator inside your class – Make mock object injection difficult• Dependency Injection – Inject dependencies through injectors – Injection method • Constructor • Setter • Dependency Injection Framework
    27. 27. AlertSystem again• AlertSystem (Hard to Test) – Concrete classes – Make Your Own Dependencies class AlertSystem { public function send_notify($content) { $target_provider = new FileNotifyTargetProvider(data.txt); $notifier = new EmailNotifier(user, pass, $port); $notify_targets = $target_provider->get_targets(); foreach ($notify_targets as $target) { $notifier->notify($target, $content); } } }
    28. 28. AlertSystem constructor injection• Constructor Injectionclass AlertSystem { protected $_notifier; protected $_target_provider; function __construct ( NotifierInterface $notifier, NotifyTargetProviderInterface $provider ) { $this->_notifier = $notifier; $this->_target_provider = $provider; } public function send_notify($content) { $notify_targets = $this->_target_provider->get_targets(); foreach ($notify_targets as $target) { $this->_notifier->notify($target, $content); } }}
    29. 29. Not only for testing• Single Responsibility Principle – Should alert system holds notifier and data provider logic? – Ex. Should the class read registry directly?• Dependency Inversion Principle• Open Close Principle
    30. 30. The Law of Demeter• Definition – Each unit should have only limited knowledge about other units: only units "closely" related to the current unit. – Each unit should only talk to its friends; dont talk to strangers. – Only talk to your immediate friends.
    31. 31. Violation of the Law• How do you test for? – Mock for mock object, for another mock object – Like Looking for a Needle in the Haystack class Monitor { SparkPlug sparkPlug; Monitor(Context context) { this.sparkPlug = context. getCar().getEngine(). getPiston().getSparkPlug(); } }
    32. 32. Law of Demeter - Explicit• Explicit – We should not need to know the details of collaborators class Mechanic { Engine engine; Mechanic(Engine engine) { this.engine = engine; } }
    33. 33. Guide – Write Testable Code• Bad smell for non-testable Code – Constructor does real work – Digging into collaborators – Brittle Global State & Singletons – Class Does Too Much• References – Guide – Write Testable Code – http://misko.hevery.com/attachments/Guide- Writing%20Testable%20Code.pdf
    34. 34. Conclusion• Writing good unit tests is hard• Good OO design brings good testability• Using stub/mock from mocking framework
    35. 35. Q&A
    36. 36. PHPUnit Log File• Junit Format<testsuites> <testsuite name="AlertSystemTest"file="/usr/home/hubert/own/work/trend/process/CI/php/tests/AlertSystemTest.php" tests="2" assertions="0" failures="1" errors="0"time="0.031119"> <testcase name="test_sendNotify_FakeNStub_NoException"class="AlertSystemTest"file="/usr/home/hubert/own/work/trend/process/CI/php/tests/AlertSystemTest.php" line="8" assertions="0" time="0.006881"/> </testsuite></testsuites>
    37. 37. PHPUnit Coverage• PHPUnit Coverage – Need Xdebug – HTML format
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×