SlideShare a Scribd company logo
© Asprotunity Ltd
Giovanni Asproni
email: gasproni@asprotunity.com
twitter: @gasproni
linkedin: http://www.linkedin.com/in/gasproni
Faking Hell
Use, abuse and misuse of fakes, mocks and other test doubles
1
© Asprotunity Ltd
Test Doubles
• Sometimes we need to test classes that interact with other objects which are difficult to control
• The real object has nondeterministic behaviour (e.g., random number generator)
• The real object is difficult to set up (e.g., requiring a certain file system, database, or network
environment)
• The real object has behaviour that is hard to trigger (e.g., a network error)
• The real object is slow
• The real object has (or is) a user interface
• The test needs to ask the real object about how it was used (e.g., confirm that a callback
function was actually called)
• The real object does not yet exist (e.g., interfacing with other teams or new hardware
systems)
2
© Asprotunity Ltd
Test Doubles
• Dummies
• Stubs
• Spies
• Fakes
• Mocks
3
© Asprotunity Ltd
Dummies
• Dummy objects are passed around but never
actually used
• E.g., a mandatory argument in a constructor never
used during a specific test
4
© Asprotunity Ltd
Stubs
• Stubs provide canned answers to calls made during
the test
5
© Asprotunity Ltd
Spies
• Spies are stubs that also record some information
based on how they were called. (e.g., the number of
times a method has been called)
6
© Asprotunity Ltd 7
public class OrderStateTest {
private static String TALISKER = "Talisker";
private WarehouseStub warehouse = new WarehouseStub();
@Test
public void orderIsFilledIfEnoughInWarehouse() {
Order order = new Order(TALISKER, 50);
order.fill(warehouse);
assertTrue(order.isFilled())
assertTrue(warehouse.removeCalled);
}
@Test
public void orderDoesNotRemoveIfNotEnough() {
Order order = new Order(TALISKER, 51);
order.fill(warehouse);
assertFalse(order.isFilled());
assertFalse(warehouse.removeCalled);
}
}
Adapted from: http://martinfowler.com/articles/mocksArentStubs.html
public class WarehouseStub implements Warehouse {
public boolean removeCalled = false;
public void hasInventory(String brand, int amount) {
return “Talisker”.equals(brand) && amount <= 50
}
public void remove(String brand, int amount) {
removeCalled = true;
}
…..
}
© Asprotunity Ltd
Fakes
• Fake objects actually have working
implementations, but take some shortcuts which
make them not suitable for production (e.g., an in
memory database)
8
© Asprotunity Ltd 9
public class OrderStateTest {
private static String TALISKER = "Talisker";
private Warehouse warehouse = new WarehouseFake();
@Test
public void orderIsFilledIfEnoughInWarehouse() {
Order order = new Order(TALISKER, 50);
order.fill(warehouse);
assertTrue(order.isFilled())
}
@Test
public void orderDoesNotRemoveIfNotEnough() {
Order order = new Order(TALISKER, 51);
order.fill(warehouse);
assertFalse(order.isFilled());
}
}
Adapted from: http://martinfowler.com/articles/mocksArentStubs.html
public class WarehouseFake implements Warehouse {
private HashMap<String, Integer> inventoryByBrand;
public WarehouseFake() {
inventoryByBrand =
new HashMap<>(){{put(“Talisker”, 50);}}
}
public void hasInventory(String brand, int required) {
available = inventoryByBrand.get(brand)
return available != null && required <= available;
}
public void remove(String brand, int amount) {
available = inventoryByBrand.get(brand)
if (available == null || amount > available) {
// Manage the error…
}
else {
inventoryByBrand.put(brand, available - amount);
}
}
…..
}
© Asprotunity Ltd
Mocks
• Mocks are objects pre-programmed with
expectations which form a specification of the calls
they are expected to receive
10
© Asprotunity Ltd
History of MockObjects
• Invented at Connextra and XtC in 1999
• The initial purpose was to get rid of getters in testing
• Component composition
• Tell don’t ask
• Testing behaviours
• More at http://www.mockobjects.com/2009/09/brief-
history-of-mock-objects.html
11
© Asprotunity Ltd 12
Adapted from: http://martinfowler.com/articles/mocksArentStubs.html
@Test
public void fillingDoesNotRemoveIfNotEnoughInStock() {
Order order = new Order(TALISKER, 51);
Mockery context = new JUnit4Mockery();
Warehouse mockWarehouse = context.mock(Warehouse.class);
//setup - expectations
context.checking(new Expectations() {{
oneOf(mockWarehouse).hasInventory(with(any(String.class)), with(any(int.class)));
will(returnValue(false));
never(mockWarehouse).remove(with(any(String.class)), with(any(int.class)));
}});
order.fill(mockWarehouse));
context.assertIsSatisfied();
assertFalse(order.isFilled());
}
© Asprotunity Ltd
Mocks Aren’t Stubs
• Mocks are meant for testing behaviour
• Stubs and all other doubles are generally used for
testing state
• Classic TDD vs Mockist TDD (Classic school vs
London School of TDD)
13
http://martinfowler.com/articles/mocksArentStubs.html
© Asprotunity Ltd 14
public class OrderStateTest {
private static String TALISKER = "Talisker";
private Warehouse warehouse = new WarehouseStub();
@Test
public void orderIsFilledIfEnoughInWarehouse() {
Order order = new Order(TALISKER, 50);
order.fill(warehouse);
assertTrue(order.isFilled())
}
@Test
public void orderDoesNotRemoveIfNotEnough() {
Order order = new Order(TALISKER, 51);
order.fill(warehouse);
assertFalse(order.isFilled());
}
}
Adapted from: http://martinfowler.com/articles/mocksArentStubs.html
public class WarehouseStub implements Warehouse {
public void hasInventory(String brand, int amount) {
return “Talisker”.equals(brand) && amount <= 50
}
public void remove(String brand, int amount) {
// Intentionally blank
}
…..
}
© Asprotunity Ltd 15
public class OrderInteractionTest {
private static String TALISKER = "Talisker";
@Test
public void fillingRemovesInventoryIfInStock() {
//setup - data
Order order = new Order(TALISKER, 50);
Mockery context = new JUnit4Mockery();
Warehouse mockWarehouse = context.mock(Warehouse.class);
//setup - expectations
context.checking(new Expectations() {{
oneOf(mockWarehouse).hasInventory(TALISKER, 50);
will(returnValue(true));
oneOf(mockWarehouse).remove(TALISKER, 50);
}});
order.fill(mockWarehouse);
context.assertIsSatisfied();
assertTrue(order.isFilled());
}
Adapted from: http://martinfowler.com/articles/mocksArentStubs.html
© Asprotunity Ltd 16
Adapted from: http://martinfowler.com/articles/mocksArentStubs.html
@Test
public void fillingDoesNotRemoveIfNotEnoughInStock() {
Order order = new Order(TALISKER, 51);
Mockery context = new JUnit4Mockery();
Warehouse mockWarehouse = context.mock(Warehouse.class);
//setup - expectations
context.checking(new Expectations() {{
oneOf(mockWarehouse).hasInventory(with(any(String.class)), with(any(int.class)));
will(returnValue(false));
never(mockWarehouse).remove(with(any(String.class)), with(any(int.class)));
}});
order.fill(mockWarehouse));
context.assertIsSatisfied();
assertFalse(order.isFilled());
}
© Asprotunity Ltd 17
Outside-In And Middle-Out
Database
Client
GUI Domain layer Server
Walking skeleton
© Asprotunity Ltd
Sometimes we need to test
state, sometimes we need
to test behaviour, and
sometimes we need both
18
State Or Behaviour?
© Asprotunity Ltd
Problems Frequently Due To
• The design of the application is unfit for purpose
• The test has no clear purpose
• Plain old confusion
• …I just want to increase code coverage…
19
© Asprotunity Ltd
The Design Of The Application Is Unfit For
Purpose
• Too many dependencies to mock
• Too many interactions with a single mock object
• Mocks nested into each other
20
© Asprotunity Ltd
The Test Has No Clear Purpose
• Testing state or behaviour?
• Fakes or stubs used to test behaviour
• Use of mock objects used to test state
21
© Asprotunity Ltd 22
public class OrderStateTest {
private static String TALISKER = "Talisker";
private WarehouseStub warehouse = new WarehouseStub();
@Test
public void orderIsFilledIfEnoughInWarehouse() {
Order order = new Order(TALISKER, 50);
order.fill(warehouse);
assertTrue(order.isFilled())
assertTrue(warehouse.removeCalled);
}
@Test
public void orderDoesNotRemoveIfNotEnough() {
Order order = new Order(TALISKER, 51);
order.fill(warehouse);
assertFalse(order.isFilled());
assertFalse(warehouse.removeCalled);
}
}
Adapted from: http://martinfowler.com/articles/mocksArentStubs.html
public class WarehouseStub implements Warehouse {
public boolean removeCalled = false;
public void hasInventory(String brand, int amount) {
return “Talisker”.equals(brand) && amount <= 50
}
public void remove(String brand, int amount) {
removeCalled = true;
}
…..
}
© Asprotunity Ltd 23
public class OrderInteractionTest {
private static String TALISKER = "Talisker";
@Test
public void fillingRemovesInventoryIfInStock() {
//setup - data
Order order = new Order(TALISKER, 50);
Mockery context = new JUnit4Mockery();
Warehouse mockWarehouse = context.mock(Warehouse.class);
//setup - expectations
context.checking(new Expectations() {{
oneOf(mockWarehouse).hasInventory(TALISKER, 50);
will(returnValue(true));
oneOf(mockWarehouse).remove(TALISKER, 50);
}});
order.fill(mockWarehouse);
// We don’t check that context.assertIsSatisfied();
assertTrue(order.isFilled());
}
Adapted from: http://martinfowler.com/articles/mocksArentStubs.html
© Asprotunity Ltd
Plain Old Confusion
• Testing the mocks
• Too many dependencies or interactions
• Partial mocking
24
© Asprotunity Ltd 25
…I just want to increase code coverage…
© Asprotunity Ltd
The Solution To Those Problems?
• Learn to listen to what the tests are telling you
• Avoid dubious practices as much as possible
• Partial mocks
• Mocking concrete classes
• Monkey patching
26
© Asprotunity Ltd 27
To Mock Or Not To Mock?
© Asprotunity Ltd
Test Doubles: Some Advantages
• Clarify which interactions are actually important for
the test
• Help in design protocols
• Make testing of some behaviours possible
• Allows for creation of faster tests
• Can alleviate dependencies on other teams
28
© Asprotunity Ltd
Test Doubles: Some (Alleged) Disadvantages
• Duplication of effort
• Changes of behaviour of the real object need to
be reflected in the test doubles
• Tests coupled to implementation (in case of mocks)
29
© Asprotunity Ltd
I’m Biased
• I find test doubles useful
• The important thing is to know which ones to use when
• …and when it’s best to use the real object
• The real object is“simple”to build and to interact with
• Full system tests
• Etc.
30
© Asprotunity Ltd 31
Questions?
© Asprotunity Ltd 32

More Related Content

PPTX
The uniform interface is 42
PDF
Tests unitaires mock_kesako_20130516
PDF
Google guava
KEY
Taking a Test Drive
PDF
0003 es5 핵심 정리
PDF
Google Guava & EMF @ GTUG Nantes
PDF
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
PDF
Java 7 LavaJUG
The uniform interface is 42
Tests unitaires mock_kesako_20130516
Google guava
Taking a Test Drive
0003 es5 핵심 정리
Google Guava & EMF @ GTUG Nantes
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 LavaJUG

What's hot (20)

PPTX
Writing and using Hamcrest Matchers
PDF
No SQL Unit - Devoxx 2012
PDF
Server1
PDF
Google guava overview
PDF
Testing the waters of iOS
PDF
ActiveRecord Query Interface (1), Season 1
PDF
Developer Test - Things to Know
PPTX
Down to Stack Traces, up from Heap Dumps
PDF
soft-shake.ch - Java SE 7: The Fork/Join Framework and Project Coin
DOCX
201913046 wahyu septiansyah network programing
PDF
Conf soat tests_unitaires_Mockito_jUnit_170113
PPTX
J unit스터디슬라이드
PDF
Google Guava
PDF
Software Testing - Invited Lecture at UNSW Sydney
PDF
The core libraries you always wanted - Google Guava
PPTX
Executable documentation
PPTX
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
PDF
PDF
Recommending Method Invocation Context Changes
PDF
COScheduler In Depth
Writing and using Hamcrest Matchers
No SQL Unit - Devoxx 2012
Server1
Google guava overview
Testing the waters of iOS
ActiveRecord Query Interface (1), Season 1
Developer Test - Things to Know
Down to Stack Traces, up from Heap Dumps
soft-shake.ch - Java SE 7: The Fork/Join Framework and Project Coin
201913046 wahyu septiansyah network programing
Conf soat tests_unitaires_Mockito_jUnit_170113
J unit스터디슬라이드
Google Guava
Software Testing - Invited Lecture at UNSW Sydney
The core libraries you always wanted - Google Guava
Executable documentation
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
Recommending Method Invocation Context Changes
COScheduler In Depth
Ad

Viewers also liked (20)

PDF
Software Configuration Management Problemas e Soluções
PPTX
WANTED: Seeking Single Agile Knowledge Development Tool-set
PPT
P4 Branching Overview
PDF
How do you deliver your applications to the cloud?
PDF
Go2Group_secrets of high-performing software teams_EAD event_san jose_Doug Bass
PDF
Is agile adoption losing steam?
PPT
Tui Travel - Overcoming the Challenges of Agile Methods
PPTX
Trustworthy Transparency and Lean Traceability
PPTX
Continuous delivery made possible
PPTX
DBTA Data Summit : Eliminating the data constraint in Application Development
PDF
Delphix modernization whitepaper
PPTX
Delphix and DBmaestro
PPTX
Kscope 2013 delphix
PPTX
In (database) automation we trust
PPTX
Jenkins Plugin
PPTX
Agile Configuration Management Environments
PDF
Test case management and requirements traceability
PPTX
Delphix Workflow for SQL Server
PPTX
Preventing the Next Deployment Issue with Continuous Performance Testing and ...
PDF
MuleSoft Connect 2015 - Go2Group presentation
Software Configuration Management Problemas e Soluções
WANTED: Seeking Single Agile Knowledge Development Tool-set
P4 Branching Overview
How do you deliver your applications to the cloud?
Go2Group_secrets of high-performing software teams_EAD event_san jose_Doug Bass
Is agile adoption losing steam?
Tui Travel - Overcoming the Challenges of Agile Methods
Trustworthy Transparency and Lean Traceability
Continuous delivery made possible
DBTA Data Summit : Eliminating the data constraint in Application Development
Delphix modernization whitepaper
Delphix and DBmaestro
Kscope 2013 delphix
In (database) automation we trust
Jenkins Plugin
Agile Configuration Management Environments
Test case management and requirements traceability
Delphix Workflow for SQL Server
Preventing the Next Deployment Issue with Continuous Performance Testing and ...
MuleSoft Connect 2015 - Go2Group presentation
Ad

Similar to Faking Hell (20)

PDF
Devday2016 real unittestingwithmockframework-phatvu
PDF
[DevDay 2016] Real Unit Testing with mocking framework - Speaker: Phat Vu – S...
PDF
Understanding Mocks
KEY
Testing w-mocks
PDF
Don't Be Mocked by your Mocks - Best Practices using Mocks
PDF
Unit Testing and role of Test doubles
PDF
Mockito tutorial
PPTX
Mock with Mockito
PPT
Xp Day 080506 Unit Tests And Mocks
PDF
Mocks, Stubs and Fakes. ¿What Else?
PPTX
Junit mockito and PowerMock in Java
PPTX
Mocking with Moq
PPTX
Mocking - Visug session
PDF
Android Test Driven Development & Android Unit Testing
PDF
An Introduction To Unit Testing and TDD
PPTX
JUnit Test Case With Processminer modules.pptx
PPTX
Test-Driven Design Insights@DevoxxBE 2023.pptx
PDF
Mockito intro
PPT
Testing – With Mock Objects
PDF
Make it test-driven with CDI!
Devday2016 real unittestingwithmockframework-phatvu
[DevDay 2016] Real Unit Testing with mocking framework - Speaker: Phat Vu – S...
Understanding Mocks
Testing w-mocks
Don't Be Mocked by your Mocks - Best Practices using Mocks
Unit Testing and role of Test doubles
Mockito tutorial
Mock with Mockito
Xp Day 080506 Unit Tests And Mocks
Mocks, Stubs and Fakes. ¿What Else?
Junit mockito and PowerMock in Java
Mocking with Moq
Mocking - Visug session
Android Test Driven Development & Android Unit Testing
An Introduction To Unit Testing and TDD
JUnit Test Case With Processminer modules.pptx
Test-Driven Design Insights@DevoxxBE 2023.pptx
Mockito intro
Testing – With Mock Objects
Make it test-driven with CDI!

More from Giovanni Asproni (9)

PDF
Remote Mob Programming In A High Stakes Environment (Agile Manchester 2023)
PDF
Remote mobprogrammingina highstakesenvironment
PDF
Creating An Incremental Architecture For Your System
PDF
Scaling Agile Done Right (XP 2017 version)
PDF
Scaling Agile Done Right (Agile Manchester 2017)
PDF
Creating An Incremental Architecture For Your System
PDF
Design For Testability
PDF
Methodology Patterns (Agile Cambridge 2014)
PDF
Writing usableap isinpractice
Remote Mob Programming In A High Stakes Environment (Agile Manchester 2023)
Remote mobprogrammingina highstakesenvironment
Creating An Incremental Architecture For Your System
Scaling Agile Done Right (XP 2017 version)
Scaling Agile Done Right (Agile Manchester 2017)
Creating An Incremental Architecture For Your System
Design For Testability
Methodology Patterns (Agile Cambridge 2014)
Writing usableap isinpractice

Recently uploaded (20)

PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PPTX
ManageIQ - Sprint 268 Review - Slide Deck
PDF
medical staffing services at VALiNTRY
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PPTX
Online Work Permit System for Fast Permit Processing
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PDF
System and Network Administration Chapter 2
PDF
top salesforce developer skills in 2025.pdf
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
ManageIQ - Sprint 268 Review - Slide Deck
medical staffing services at VALiNTRY
Softaken Excel to vCard Converter Software.pdf
Wondershare Filmora 15 Crack With Activation Key [2025
Design an Analysis of Algorithms II-SECS-1021-03
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Online Work Permit System for Fast Permit Processing
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Upgrade and Innovation Strategies for SAP ERP Customers
Which alternative to Crystal Reports is best for small or large businesses.pdf
Design an Analysis of Algorithms I-SECS-1021-03
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
System and Network Administration Chapter 2
top salesforce developer skills in 2025.pdf
How to Migrate SBCGlobal Email to Yahoo Easily

Faking Hell

  • 1. © Asprotunity Ltd Giovanni Asproni email: gasproni@asprotunity.com twitter: @gasproni linkedin: http://www.linkedin.com/in/gasproni Faking Hell Use, abuse and misuse of fakes, mocks and other test doubles 1
  • 2. © Asprotunity Ltd Test Doubles • Sometimes we need to test classes that interact with other objects which are difficult to control • The real object has nondeterministic behaviour (e.g., random number generator) • The real object is difficult to set up (e.g., requiring a certain file system, database, or network environment) • The real object has behaviour that is hard to trigger (e.g., a network error) • The real object is slow • The real object has (or is) a user interface • The test needs to ask the real object about how it was used (e.g., confirm that a callback function was actually called) • The real object does not yet exist (e.g., interfacing with other teams or new hardware systems) 2
  • 3. © Asprotunity Ltd Test Doubles • Dummies • Stubs • Spies • Fakes • Mocks 3
  • 4. © Asprotunity Ltd Dummies • Dummy objects are passed around but never actually used • E.g., a mandatory argument in a constructor never used during a specific test 4
  • 5. © Asprotunity Ltd Stubs • Stubs provide canned answers to calls made during the test 5
  • 6. © Asprotunity Ltd Spies • Spies are stubs that also record some information based on how they were called. (e.g., the number of times a method has been called) 6
  • 7. © Asprotunity Ltd 7 public class OrderStateTest { private static String TALISKER = "Talisker"; private WarehouseStub warehouse = new WarehouseStub(); @Test public void orderIsFilledIfEnoughInWarehouse() { Order order = new Order(TALISKER, 50); order.fill(warehouse); assertTrue(order.isFilled()) assertTrue(warehouse.removeCalled); } @Test public void orderDoesNotRemoveIfNotEnough() { Order order = new Order(TALISKER, 51); order.fill(warehouse); assertFalse(order.isFilled()); assertFalse(warehouse.removeCalled); } } Adapted from: http://martinfowler.com/articles/mocksArentStubs.html public class WarehouseStub implements Warehouse { public boolean removeCalled = false; public void hasInventory(String brand, int amount) { return “Talisker”.equals(brand) && amount <= 50 } public void remove(String brand, int amount) { removeCalled = true; } ….. }
  • 8. © Asprotunity Ltd Fakes • Fake objects actually have working implementations, but take some shortcuts which make them not suitable for production (e.g., an in memory database) 8
  • 9. © Asprotunity Ltd 9 public class OrderStateTest { private static String TALISKER = "Talisker"; private Warehouse warehouse = new WarehouseFake(); @Test public void orderIsFilledIfEnoughInWarehouse() { Order order = new Order(TALISKER, 50); order.fill(warehouse); assertTrue(order.isFilled()) } @Test public void orderDoesNotRemoveIfNotEnough() { Order order = new Order(TALISKER, 51); order.fill(warehouse); assertFalse(order.isFilled()); } } Adapted from: http://martinfowler.com/articles/mocksArentStubs.html public class WarehouseFake implements Warehouse { private HashMap<String, Integer> inventoryByBrand; public WarehouseFake() { inventoryByBrand = new HashMap<>(){{put(“Talisker”, 50);}} } public void hasInventory(String brand, int required) { available = inventoryByBrand.get(brand) return available != null && required <= available; } public void remove(String brand, int amount) { available = inventoryByBrand.get(brand) if (available == null || amount > available) { // Manage the error… } else { inventoryByBrand.put(brand, available - amount); } } ….. }
  • 10. © Asprotunity Ltd Mocks • Mocks are objects pre-programmed with expectations which form a specification of the calls they are expected to receive 10
  • 11. © Asprotunity Ltd History of MockObjects • Invented at Connextra and XtC in 1999 • The initial purpose was to get rid of getters in testing • Component composition • Tell don’t ask • Testing behaviours • More at http://www.mockobjects.com/2009/09/brief- history-of-mock-objects.html 11
  • 12. © Asprotunity Ltd 12 Adapted from: http://martinfowler.com/articles/mocksArentStubs.html @Test public void fillingDoesNotRemoveIfNotEnoughInStock() { Order order = new Order(TALISKER, 51); Mockery context = new JUnit4Mockery(); Warehouse mockWarehouse = context.mock(Warehouse.class); //setup - expectations context.checking(new Expectations() {{ oneOf(mockWarehouse).hasInventory(with(any(String.class)), with(any(int.class))); will(returnValue(false)); never(mockWarehouse).remove(with(any(String.class)), with(any(int.class))); }}); order.fill(mockWarehouse)); context.assertIsSatisfied(); assertFalse(order.isFilled()); }
  • 13. © Asprotunity Ltd Mocks Aren’t Stubs • Mocks are meant for testing behaviour • Stubs and all other doubles are generally used for testing state • Classic TDD vs Mockist TDD (Classic school vs London School of TDD) 13 http://martinfowler.com/articles/mocksArentStubs.html
  • 14. © Asprotunity Ltd 14 public class OrderStateTest { private static String TALISKER = "Talisker"; private Warehouse warehouse = new WarehouseStub(); @Test public void orderIsFilledIfEnoughInWarehouse() { Order order = new Order(TALISKER, 50); order.fill(warehouse); assertTrue(order.isFilled()) } @Test public void orderDoesNotRemoveIfNotEnough() { Order order = new Order(TALISKER, 51); order.fill(warehouse); assertFalse(order.isFilled()); } } Adapted from: http://martinfowler.com/articles/mocksArentStubs.html public class WarehouseStub implements Warehouse { public void hasInventory(String brand, int amount) { return “Talisker”.equals(brand) && amount <= 50 } public void remove(String brand, int amount) { // Intentionally blank } ….. }
  • 15. © Asprotunity Ltd 15 public class OrderInteractionTest { private static String TALISKER = "Talisker"; @Test public void fillingRemovesInventoryIfInStock() { //setup - data Order order = new Order(TALISKER, 50); Mockery context = new JUnit4Mockery(); Warehouse mockWarehouse = context.mock(Warehouse.class); //setup - expectations context.checking(new Expectations() {{ oneOf(mockWarehouse).hasInventory(TALISKER, 50); will(returnValue(true)); oneOf(mockWarehouse).remove(TALISKER, 50); }}); order.fill(mockWarehouse); context.assertIsSatisfied(); assertTrue(order.isFilled()); } Adapted from: http://martinfowler.com/articles/mocksArentStubs.html
  • 16. © Asprotunity Ltd 16 Adapted from: http://martinfowler.com/articles/mocksArentStubs.html @Test public void fillingDoesNotRemoveIfNotEnoughInStock() { Order order = new Order(TALISKER, 51); Mockery context = new JUnit4Mockery(); Warehouse mockWarehouse = context.mock(Warehouse.class); //setup - expectations context.checking(new Expectations() {{ oneOf(mockWarehouse).hasInventory(with(any(String.class)), with(any(int.class))); will(returnValue(false)); never(mockWarehouse).remove(with(any(String.class)), with(any(int.class))); }}); order.fill(mockWarehouse)); context.assertIsSatisfied(); assertFalse(order.isFilled()); }
  • 17. © Asprotunity Ltd 17 Outside-In And Middle-Out Database Client GUI Domain layer Server Walking skeleton
  • 18. © Asprotunity Ltd Sometimes we need to test state, sometimes we need to test behaviour, and sometimes we need both 18 State Or Behaviour?
  • 19. © Asprotunity Ltd Problems Frequently Due To • The design of the application is unfit for purpose • The test has no clear purpose • Plain old confusion • …I just want to increase code coverage… 19
  • 20. © Asprotunity Ltd The Design Of The Application Is Unfit For Purpose • Too many dependencies to mock • Too many interactions with a single mock object • Mocks nested into each other 20
  • 21. © Asprotunity Ltd The Test Has No Clear Purpose • Testing state or behaviour? • Fakes or stubs used to test behaviour • Use of mock objects used to test state 21
  • 22. © Asprotunity Ltd 22 public class OrderStateTest { private static String TALISKER = "Talisker"; private WarehouseStub warehouse = new WarehouseStub(); @Test public void orderIsFilledIfEnoughInWarehouse() { Order order = new Order(TALISKER, 50); order.fill(warehouse); assertTrue(order.isFilled()) assertTrue(warehouse.removeCalled); } @Test public void orderDoesNotRemoveIfNotEnough() { Order order = new Order(TALISKER, 51); order.fill(warehouse); assertFalse(order.isFilled()); assertFalse(warehouse.removeCalled); } } Adapted from: http://martinfowler.com/articles/mocksArentStubs.html public class WarehouseStub implements Warehouse { public boolean removeCalled = false; public void hasInventory(String brand, int amount) { return “Talisker”.equals(brand) && amount <= 50 } public void remove(String brand, int amount) { removeCalled = true; } ….. }
  • 23. © Asprotunity Ltd 23 public class OrderInteractionTest { private static String TALISKER = "Talisker"; @Test public void fillingRemovesInventoryIfInStock() { //setup - data Order order = new Order(TALISKER, 50); Mockery context = new JUnit4Mockery(); Warehouse mockWarehouse = context.mock(Warehouse.class); //setup - expectations context.checking(new Expectations() {{ oneOf(mockWarehouse).hasInventory(TALISKER, 50); will(returnValue(true)); oneOf(mockWarehouse).remove(TALISKER, 50); }}); order.fill(mockWarehouse); // We don’t check that context.assertIsSatisfied(); assertTrue(order.isFilled()); } Adapted from: http://martinfowler.com/articles/mocksArentStubs.html
  • 24. © Asprotunity Ltd Plain Old Confusion • Testing the mocks • Too many dependencies or interactions • Partial mocking 24
  • 25. © Asprotunity Ltd 25 …I just want to increase code coverage…
  • 26. © Asprotunity Ltd The Solution To Those Problems? • Learn to listen to what the tests are telling you • Avoid dubious practices as much as possible • Partial mocks • Mocking concrete classes • Monkey patching 26
  • 27. © Asprotunity Ltd 27 To Mock Or Not To Mock?
  • 28. © Asprotunity Ltd Test Doubles: Some Advantages • Clarify which interactions are actually important for the test • Help in design protocols • Make testing of some behaviours possible • Allows for creation of faster tests • Can alleviate dependencies on other teams 28
  • 29. © Asprotunity Ltd Test Doubles: Some (Alleged) Disadvantages • Duplication of effort • Changes of behaviour of the real object need to be reflected in the test doubles • Tests coupled to implementation (in case of mocks) 29
  • 30. © Asprotunity Ltd I’m Biased • I find test doubles useful • The important thing is to know which ones to use when • …and when it’s best to use the real object • The real object is“simple”to build and to interact with • Full system tests • Etc. 30
  • 31. © Asprotunity Ltd 31 Questions?