This document provides an overview of mocks and stubs in testing, using Ruby and RSpec examples. It establishes common terminology around mock objects, shows appropriate uses of mocks such as defining interfaces and simulating situations, and demonstrates abuses such as modifying the subject under test and creating "mock trainwrecks" that tie specs too tightly to implementation details. The goal is to understand best practices for using mocks to write clear, maintainable tests.
Love it or hate it, JavaScript is playing an increasingly important role in the next generation of web and mobile apps. As code continues to move from the server to the client, JavaScript is being used to do more than simple HTML manipulation. Be prepared for this transition and make sure the JavaScript you write is optimized and ready to perform on desktops and devices! In this session, you will learn ten practical tips that you can use today to write faster, more maintainable, memory friendly JavaScript.
We <3 .rb
but - still .rb < perfect
This presentation shows some of the ways that this language, engineered for maximum programmer happiness and least surprise, can still have some nasty gotchas.
Presentation derived from the "What's new in Python 2.6" document on http://www.python.org/ including much reformatting for presenting and presenter notes.
Please download the Keynote original - that way the presentation notes aren't burned into the slides.
This presentation will give you a brief background to JavaScript, what it is and where it comes from. Then it will walk you through general pitfalls, best practices and more advanced topics such as object-orientation, scope and closures.
Esoft Metro Campus - Diploma in Web Engineering - (Module II) Multimedia Technologies
(Template - Virtusa Corporate)
Contents:
What is a Database?
The Relational Data Model
Relationships
Normalization
Functional Dependency
Normal Forms
DBMS
What is MySQL?
PHP Connect to MySQL
Create a MySQL Database
Connect to Database
Close Database
Create a MySQL Table
Insert Data Into MySQL
Get Last ID
Insert Multiple Records
Prepared Statements
Select Data From MySQL
Update Data in MySQL
Delete Data From MySQL
non-strict functions, bottom and scala by-name parametersPhilip Schwarz
Ā
Download for perfect quality.
Non strict functions, bottom and scala by-name parameters - āa close lookā, through the work of Runar Bjarnason, Paul Chiusano, Martin Odersky, Bill Venners, Lex Spoon, Alvin Alexander, Mark Lewis and Aleksandar Prokopec.
Slides from talk given at Ithaca Web Group and GORGES on CoffeeScript.
The focus is on explaining to people who haven't tried it yet that it's more than syntactic sugar. There are several real life code examples but they were explained verbally so they may not be super helpful if you don't know CoffeeScript yet.
It's an overview, not a tutorial.
Love it or hate it, JavaScript is playing an increasingly important role in the next generation of web and mobile apps. As code continues to move from the server to the client, JavaScript is being used to do more than simple HTML manipulation. Be prepared for this transition and make sure the JavaScript you write is optimized and ready to perform on desktops and devices! In this session, you will learn ten practical tips that you can use today to write faster, more maintainable, memory friendly JavaScript.
We <3 .rb
but - still .rb < perfect
This presentation shows some of the ways that this language, engineered for maximum programmer happiness and least surprise, can still have some nasty gotchas.
Presentation derived from the "What's new in Python 2.6" document on http://www.python.org/ including much reformatting for presenting and presenter notes.
Please download the Keynote original - that way the presentation notes aren't burned into the slides.
This presentation will give you a brief background to JavaScript, what it is and where it comes from. Then it will walk you through general pitfalls, best practices and more advanced topics such as object-orientation, scope and closures.
Esoft Metro Campus - Diploma in Web Engineering - (Module II) Multimedia Technologies
(Template - Virtusa Corporate)
Contents:
What is a Database?
The Relational Data Model
Relationships
Normalization
Functional Dependency
Normal Forms
DBMS
What is MySQL?
PHP Connect to MySQL
Create a MySQL Database
Connect to Database
Close Database
Create a MySQL Table
Insert Data Into MySQL
Get Last ID
Insert Multiple Records
Prepared Statements
Select Data From MySQL
Update Data in MySQL
Delete Data From MySQL
non-strict functions, bottom and scala by-name parametersPhilip Schwarz
Ā
Download for perfect quality.
Non strict functions, bottom and scala by-name parameters - āa close lookā, through the work of Runar Bjarnason, Paul Chiusano, Martin Odersky, Bill Venners, Lex Spoon, Alvin Alexander, Mark Lewis and Aleksandar Prokopec.
Slides from talk given at Ithaca Web Group and GORGES on CoffeeScript.
The focus is on explaining to people who haven't tried it yet that it's more than syntactic sugar. There are several real life code examples but they were explained verbally so they may not be super helpful if you don't know CoffeeScript yet.
It's an overview, not a tutorial.
There are many things that make Ruby a great language, but above all else, the beautiful and friendly syntax. A perfect exemplar of this is the case statement: case enables a flexible method of dispatching on an object that is both natural and intuitive. But case can't do it alone. No, it requires the help of it's little-known and under-appreciated sidekick the === (threequals) operator.
In this talk we'll dive into this fascinating corner of the Ruby language and see what trouble we can cause with the humble threequals. We'll go over the basics of how it interacts with case, and then go into some tips and tricks for making the most of this useful bit of syntax, and ultimately create a little pattern matching mini-language as a demonstration.
Apple's Swift has achieved the top place in Stack Overflow's "Most Loved" list of programming languages in its 2015 Developer Survey. Based on information gleaned from GitHub and Stack Overflow, analyst firm RedMonk has seen Swift's popularity ranking soar from 68 to 22 in an unprecedented 6 months.
The "Extreme Swift" event does not require advanced, or even any, knowledge of Swift. Learn about some of the more outrageous features of the language which help explain what the fuss is all about!
Never look at programming the same way again ā even if you never end up writing a single line of Swift code in your life.
A version of the Conflict Resolution Diagram / Evaporating Cloud talk/workshop I prepared for a SCiO Open Day in Manchester: http://www.scio.org.uk/node/760
These are the slides to a lightning talk on I gave at the PHPNW meetup on 6 Aug 2013. It's an incomplete, slightly skewed look at how I apply Personal Kanban myself. - Ash
Let's dive deeper into the world of ODC! Ricardo Alves (OutSystems) will join us to tell all about the new Data Fabric. After that, Sezen de Bruijn (OutSystems) will get into the details on how to best design a sturdy architecture within ODC.
The Art of the Pitch: WordPress Relationships and SalesLaura Byrne
Ā
Clients donāt know what they donāt know. What web solutions are right for them? How does WordPress come into the picture? How do you make sure you understand scope and timeline? What do you do if sometime changes?
All these questions and more will be explored as we talk about matching clientsā needs with what your agency offers without pulling teeth or pulling your hair out. Practical tips, and strategies for successful relationship building that leads to closing the deal.
JMeter webinar - integration with InfluxDB and GrafanaRTTS
Ā
Watch this recorded webinar about real-time monitoring of application performance. See how to integrate Apache JMeter, the open-source leader in performance testing, with InfluxDB, the open-source time-series database, and Grafana, the open-source analytics and visualization application.
In this webinar, we will review the benefits of leveraging InfluxDB and Grafana when executing load tests and demonstrate how these tools are used to visualize performance metrics.
Length: 30 minutes
Session Overviewā
-------------------------------------------
During this webinar, we will cover the following topics while demonstrating the integrations of JMeter, InfluxDB and Grafana:
- What out-of-the-box solutions are available for real-time monitoring JMeter tests?
- What are the benefits of integrating InfluxDB and Grafana into the load testing stack?
- Which features are provided by Grafana?
- Demonstration of InfluxDB and Grafana using a practice web application
To view the webinar recording, go to:
https://www.rttsweb.com/jmeter-integration-webinar
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Jeffrey Haguewood
Ā
Sidekick Solutions uses Bonterra Impact Management (fka Social Solutions Apricot) and automation solutions to integrate data for business workflows.
We believe integration and automation are essential to user experience and the promise of efficient work through technology. Automation is the critical ingredient to realizing that full vision. We develop integration products and services for Bonterra Case Management software to support the deployment of automations for a variety of use cases.
This video focuses on the notifications, alerts, and approval requests using Slack for Bonterra Impact Management. The solutions covered in this webinar can also be deployed for Microsoft Teams.
Interested in deploying notification automations for Bonterra Impact Management? Contact us at sales@sidekicksolutionsllc.com to discuss next steps.
Neuro-symbolic is not enough, we need neuro-*semantic*Frank van Harmelen
Ā
Neuro-symbolic (NeSy) AI is on the rise. However, simply machine learning on just any symbolic structure is not sufficient to really harvest the gains of NeSy. These will only be gained when the symbolic structures have an actual semantics. I give an operational definition of semantics as āpredictable inferenceā.
All of this illustrated with link prediction over knowledge graphs, but the argument is general.
Transcript: Selling digital books in 2024: Insights from industry leaders - T...BookNet Canada
Ā
The publishing industry has been selling digital audiobooks and ebooks for over a decade and has found its groove. Whatās changed? What has stayed the same? Where do we go from here? Join a group of leading sales peers from across the industry for a conversation about the lessons learned since the popularization of digital books, best practices, digital book supply chain management, and more.
Link to video recording: https://bnctechforum.ca/sessions/selling-digital-books-in-2024-insights-from-industry-leaders/
Presented by BookNet Canada on May 28, 2024, with support from the Department of Canadian Heritage.
Connector Corner: Automate dynamic content and events by pushing a buttonDianaGray10
Ā
Here is something new! In our next Connector Corner webinar, we will demonstrate how you can use a single workflow to:
Create a campaign using Mailchimp with merge tags/fields
Send an interactive Slack channel message (using buttons)
Have the message received by managers and peers along with a test email for review
But thereās more:
In a second workflow supporting the same use case, youāll see:
Your campaign sent to target colleagues for approval
If the āApproveā button is clicked, a Jira/Zendesk ticket is created for the marketing design team
Butāif the āRejectā button is pushed, colleagues will be alerted via Slack message
Join us to learn more about this new, human-in-the-loop capability, brought to you by Integration Service connectors.
And...
Speakers:
Akshay Agnihotri, Product Manager
Charlie Greenberg, Host
Search and Society: Reimagining Information Access for Radical FuturesBhaskar Mitra
Ā
The field of Information retrieval (IR) is currently undergoing a transformative shift, at least partly due to the emerging applications of generative AI to information access. In this talk, we will deliberate on the sociotechnical implications of generative AI for information access. We will argue that there is both a critical necessity and an exciting opportunity for the IR community to re-center our research agendas on societal needs while dismantling the artificial separation between the work on fairness, accountability, transparency, and ethics in IR and the rest of IR research. Instead of adopting a reactionary strategy of trying to mitigate potential social harms from emerging technologies, the community should aim to proactively set the research agenda for the kinds of systems we should build inspired by diverse explicitly stated sociotechnical imaginaries. The sociotechnical imaginaries that underpin the design and development of information access technologies needs to be explicitly articulated, and we need to develop theories of change in context of these diverse perspectives. Our guiding future imaginaries must be informed by other academic fields, such as democratic theory and critical theory, and should be co-developed with social science scholars, legal scholars, civil rights and social justice activists, and artists, among others.
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...DanBrown980551
Ā
Do you want to learn how to model and simulate an electrical network from scratch in under an hour?
Then welcome to this PowSyBl workshop, hosted by Rte, the French Transmission System Operator (TSO)!
During the webinar, you will discover the PowSyBl ecosystem as well as handle and study an electrical network through an interactive Python notebook.
PowSyBl is an open source project hosted by LF Energy, which offers a comprehensive set of features for electrical grid modelling and simulation. Among other advanced features, PowSyBl provides:
- A fully editable and extendable library for grid component modelling;
- Visualization tools to display your network;
- Grid simulation tools, such as power flows, security analyses (with or without remedial actions) and sensitivity analyses;
The framework is mostly written in Java, with a Python binding so that Python developers can access PowSyBl functionalities as well.
What you will learn during the webinar:
- For beginners: discover PowSyBl's functionalities through a quick general presentation and the notebook, without needing any expert coding skills;
- For advanced developers: master the skills to efficiently apply PowSyBl functionalities to your real-world scenarios.
GraphRAG is All You need? LLM & Knowledge GraphGuy Korland
Ā
Guy Korland, CEO and Co-founder of FalkorDB, will review two articles on the integration of language models with knowledge graphs.
1. Unifying Large Language Models and Knowledge Graphs: A Roadmap.
https://arxiv.org/abs/2306.08302
2. Microsoft Research's GraphRAG paper and a review paper on various uses of knowledge graphs:
https://www.microsoft.com/en-us/research/blog/graphrag-unlocking-llm-discovery-on-narrative-private-data/
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf91mobiles
Ā
91mobiles recently conducted a Smart TV Buyer Insights Survey in which we asked over 3,000 respondents about the TV they own, aspects they look at on a new TV, and their TV buying preferences.
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Ā
Uses & Abuses of Mocks & Stubs
1. Manchester
October 2009
Uses & Abuses
of Mocks & Stubs
With examples in Ruby using RSpec
Ashley Moran
Creative Commons Attribution-Noncommercial-Share Alike
2.0 UK: England & Wales License PatchSpace Ltd
2. Presentation goals
To establish a common language about
mock objects
To show some situations where mocks are
useful
To show some situations where mocks are
inappropriate, and problems they can
cause
3. Presentation non-goals
The slides do not attemptā¦
to teach you RSpec
to cover OO design
to use real-world code
So please ask questions if I've glossed over
anything you think I should have explained
5. Starting Point
A mock is some sort of trivial object that
can be injected into code to make writing
specs easier
A mock can be made to respond to
messages
6. Traditional Deļ¬nitions
Gerard Meszaros deļ¬nes the following
test object roles, among others:
dummy
stub
fake
mock
These are precise and signiļ¬cantly
different from each other
7. RSpec Deļ¬nitions
RSpec provides three (equivalent) factory
methods for creating mock objects
mock("my mock object")
stub("my stub object")
double("my double object")
The RSpec book uses "test double" as the
primary term; I still prefer "mock"
8. My deļ¬nitions
A mock is any trivial object injected into
your code to help describe its behaviour
A stub method is a method that returns a
canned response
This may be on a "real" object, more later
A message expectation is an expectation
that fails if a stub method is not called
appropriately in spec code
9. RSpec concepts
describe "A behaviour description" do
it "has an example" do
my_mock = mock(Object,
:stub_method => "expected value")
my_mock.stub_method.should == "expected value"
end
it "has an example with a message expectation" do
my_mock = mock(Object,
:expected_method => "value")
my_mock.should_receive(:expected_method)
my_mock.expected_method
end
end
11. Deļ¬ning an Interface
Ruby is 99% about objects and interfaces,
and 1% about classes
describe Person do
before(:each) do
@service = mock("service")
@person = Person.new("Fred", "Flintstone")
end
it "can save itself" do
@service.should_receive(:query).with(
"STORE 'Fred', 'Flintstone';"
)
@person.save(@service)
end
end
12. Deļ¬ning an Interface
The set of options for message
expectations is too large to go into now,
but is extremely ļ¬exible
describe Person do
before(:each) do
@service = mock("service")
@person = Person.new("Fred", "Flintstone")
end
it "sends relevant details" do
@service.should_receive(:confirm_family).with(
hash_including(:name => "Flintstone")
)
@person.register(@service)
end
end
13. Observable Behaviour
Sometimes you know how your code
should behave even if you ignore the
details of how it works
describe XmlDoc do
before(:each) do
body = mock("body", :to_xml => "<body />")
@doc = XmlDoc.new(body)
end
it "renders the document and body" do
@doc.to_xml.should == "<doc><body /></doc>"
end
end
14. Observable Behaviour
This is actually an appropriate situation
for a custom matcher to deliberately
weaken our expectation of the behaviour
describe XmlDoc do
# ...
it "renders the document and body" do
@doc.to_xml.should be_equivalent_xml_to(
"<doc><body /></doc>"
)
end
end
I wrote a matcher for this the other day,
but that's another talk
15. Dependency Injection
The ability to redeļ¬ne methods in Ruby
massively reduces the impact of depending on a
named class compared to eg Java
class DatabaseLogger
def initialize(connection_details)
@connection_details = connection_details
end
def log(message)
Database.new(@connection_details).log(message)
end
end
16. Dependency Injection
A stub can be used to override factory methods
describe DatabaseLogger do
before(:each) do
@connection_details = mock("connection details")
@database = mock(Database, :log => nil)
@database_logger = DatabaseLogger.new(@connection_details)
end
it "creates a new Database" do
Database.should_receive(:new).
with(@connection_details).
and_return(@database)
@database_logger.log("take note")
end
end
17. Simulating Situations
Mocks let us put our code through situations
that may be hard to recreate for real
describe ObjectSaver do
before(:each) do
@storage = mock("storage")
@object_saver = ObjectSaver.new(@storage)
end
it "should save" do
@storage.should_receive(:save).and_raise(OutOfStorageError)
@object_saver.save(nil)
end
end
Especially useful if there's a large number of
situations (true of some stdlib code)
18. Degrees of Freedom
describe Shape do
before(:each) do
@triangle = Shape.new(3)
end
it "knows how many sides it has" do
@triangle.sides.should == 3
end
end
This Shape class is one dimensional
Complaints about the examples at the end
please
Only one thing can vary - will one example do?
19. Degrees of Freedom
class Shape
def initialize(sides)
end
def sides
3
end
end
No - one example is not enough
20. Degrees of Freedom
We need t wo points to prove that the
implementation isn't simplistic
describe Shape do
before(:each) do
@triangle = Shape.new(3)
@square = Shape.new(4)
end
it "knows how many sides it has" do
@triangle.sides.should == 3
@square.sides.should == 4
end
end
21. Degrees of Freedom
We now have to solve the problem fully,
but at the expense of more spec code
class Shape
def initialize(sides)
@sides = sides
end
def sides
@sides
end
end
This is a trivial example - don't write
getters or use attr_reader in real code!
22. Degrees of Freedom
We can reduce this to one using a mock
because we can't generate something that
is == the mock from in the code
describe Shape do
before(:each) do
@triangle = Shape.new(@sides = mock("sides"))
end
it "knows how many sides it has" do
@triangle.sides.should == @sides
end
end
This technique is not always appropriate - a
getter method is simply the easiest example
24. Removing Duplication
The spec for this code is fairly complex
describe Room do
before(:each) do
@room = Room.new
end
it "opens with the right key" do
@room.open_door("sesame").should == :open
end
it "won't open with the wrong key" do
@room.open_door("now!!!").should == :closed
end
end
25. Removing Duplication
Imagine a decorator object that delegates
to it
class Bedsit
def initialize(room)
@room = room
end
def open_door(key)
@room.open_door(key)
end
def fix_roof
"it's fixed"
end
end
26. Removing Duplication
How do you write the spec?
describe Bedsit do
before(:each) do
@bedsit = Bedsit.new(Room.new)
end
it "opens with the right key" do
# WARNING - duplication!
@bedsit.open_door("sesame").should == :open
end
it "won't open with the wrong key" do
# ...
end
end
27. Removing Duplication
We actually only care about the delegation
describe Bedsit do
before(:each) do
@open_door_response = mock("open_door_response")
@key = mock("key")
@room = mock(Room, :open_door => @open_door_response)
@bedsit = Bedsit.new(@room)
end
it "delegates #open_door" do
@room.should_receive(:open_door).with(@key)
@bedsit.open_door(@key)
end
it "returns the delegated response" do
@bedsit.open_door(nil).should == @open_door_response
end
end
28. Hiding Random Behaviour
The following code may be useful to
randomise collections of data
class Randomiser
def initialize(collection)
@collection = collection
end
def to_a
@collection.sort { rand <=> 0.5 }
end
end
29. Hiding Random Behaviour
This is the client
class Sampler
def initialize(values, logger)
@values, @logger = values, logger
end
def sample
@logger.log(Randomiser.new(@values).to_a[0])
end
end
30. Hiding Random Behaviour
describe Sampler do
before(:each) do
@first = mock("first")
@randomiser = mock(Randomiser, :to_a => [@first, 2, 3])
Randomiser.stub(:new => @randomiser)
@logger = mock("logger", :log => nil)
@values = mock("values")
@sampler = Sampler.new(@values, @logger)
end
it "makes a new Randomiser" do
Randomiser.should_receive(:new).with(@values)
@sampler.sample
end
it "logs a sample of the data" do
@logger.should_receive(:log).with(@first)
@sampler.sample
end
end
31. Exploratory Coding
Following the outside in BDD principle leads
you to write client code before provider
code, eg:
A web controller before a domain model
A domain model before a storage system
Data processing before ļ¬le system
access
I'm going to defer this until the "Mock
Trainwreck" abuse later
33. Modifying the Subject
Modifying the subject of a behaviour
description is dangerous, you can:
Introduce false positives
Make the specs brittle
What I call the "subject" is sometimes
known as Object Under Test, Subject Under
Test or System Under Test
34. Modifying the Subject
This is a stable - albeit incomplete - spec
describe Person do
before(:each) do
@person = Person.new("Fred", "Flintstone")
end
it "should have a full name" do
@person.name.should == "Fred FLINTSTONE"
end
end
35. Modifying the Subject
ā¦and one of the possible implementations
class Person
def initialize(first, last)
@first, @last = first, last
end
def name
"#{@first} #{last}"
end
private
def last
@last.upcase
end
end
36. Modifying the Subject
This spec makes assumptions about the
subject
describe Person do
before(:each) do
@person = Person.new("Fred", "Flintstone")
@person.stub(:last => "FLINTSTONE")
end
it "should have a full name" do
@person.name.should == "Fred FLINTSTONE"
end
end
37. Modifying the Subject
This code silently breaks the behaviour
class Person
def initialize(first, last)
@first, @last = first, last
end
def name
"#{@first} #{last}"
end
private
def last
@last.downcase
end
end
False positives are a catastrophe!
38. Mock Mania
describe ManicObject do
before(:each) do
@db = mock(Database)
@logger = mock(Logger)
@rss_feed = mock(URI)
@kitchen_sink = mock(KitchenSink)
@cleaning_solution = mock(FairyLiquid)
end
# ...
end
Specs like this indicate a Single
Responsibility violation. The ManicObject
class is probably highly unstable
39. Mock Trainwrecks
Stub methods on non-Class objects should
not (usually) return mocks that you
interact with
This indicates a violation of Law of
Demeter in the code
Mock trainwrecks tie your specs to the
current code structure, so are brittle and
scatter the specs for the other objects
40. Mock Trainwrecks
The code that passes this spec must be
breaking encapsulation to expose its
internals
describe Train do
before(:each) do
@door = mock(Door)
@cabin = mock(Cabin, :door => @door)
@engine = mock(Engine, :cabin => @cabin)
@train = Train.new(@engine)
end
it "can lock its door" do
@door.should_receive(:lock).once
@train.lock_door
end
end
41. Mock Trainwrecks
attr_reader shows we're off to a bad start
class Train class Cabin
def initialize(engine) attr_reader :door
@engine = engine
end def initialize(door)
@door = door
def lock_door end
@engine.cabin.door.lock end
end
end
class Engine class Door
attr_reader :cabin def lock
"it's locked"
def initialize(cabin) end
@cabin = cabin end
end
end
42. Mock Trainwrecks
Let's break this down into single-step
interactions
describe Train do
before(:each) do
@engine = mock(Engine)
@train = Train.new(@engine)
end
it "locks its cabin door" do
@engine.should_receive(:lock_door).with(no_args)
@train.lock_door
end
end
43. Mock Trainwrecks
The interface to engines is now not
exposed to clients of trains
class Train
def initialize(engine)
@engine = engine
end
def lock_door
@engine.lock_door
end
end
44. Mock Trainwrecks
Apply the pattern recursivelyā¦
describe Engine do
before(:each) do
@cabin = mock(Cabin)
@engine = Engine.new(@cabin)
end
it "locks its cabin door" do
@cabin.should_receive(:lock_door).with(no_args)
@engine.lock_door
end
end
45. Mock Trainwrecks
The cabin interface is now hidden
class Engine
def initialize(cabin)
@cabin = cabin
end
def lock_door
@cabin.lock_door
end
end
46. Mock Trainwrecks
Apply againā¦
describe Cabin do
before(:each) do
@door = mock(Door)
@cabin = Cabin.new(@door)
end
it "locks its cabin door" do
@door.should_receive(:lock).with(no_args)
@cabin.lock_door
end
end
47. Mock Trainwrecks
The door interface is now hidden
class Cabin
def initialize(door)
@door = door
end
def lock_door
@door.lock
end
end
48. Mock Trainwrecks
Finally we prove that the door actually
locks
describe Door do
it "locks" do
Door.new.lock.should == "it's locked"
end
end
class Door
def lock
"it's locked"
end
end
49. Mock Trainwrecks
We've hidden the structure of our object
model, which satisļ¬es the Law of Demeter
But we've now described three internal
interfaces (on Engine, Cabin and Door)
The code can be broken if any internal
interface changes
In an unstable object model, this can lead
to a lot of rework
50. Mock Trainwrecks
We could eliminate the use of mocks from
most (or all, if we wanted) of the spec
describe Train do
before(:each) do
@door = mock(Door)
@cabin = Cabin.new(@door)
@engine = Engine.new(@cabin)
@train = Train.new(@engine)
end
it "can lock its door" do
@door.should_receive(:lock).once
@train.lock_door
end
end
Be warned that this example is contrived,
and strays far into OO design territory
51. Mock Trainwrecks
On the subject of trainwrecks
describe "thetrainline.com" do
it "should be loved by all" do
URI.parse("thetrainline.com").should_not be_shit
end
end
Unfortunately, Ruby (as of 1.9.1) does not
deļ¬ne URI#shit? so a custom matcher would
be required
53. Beneļ¬ts of Mocks
Mocks let you explore and drive out new
interfaces needing a full implementation
Mocks let you implement your code
incrementally and get to green faster
Mocks let you prove properties of your
code to the degree of precision and
strength you demand
54. Trouble from Mocks
Mocks make your specs interface-driven
not behaviour-driven
Fine if using the interface is the
behaviour
Can introduce overhead and rework if
the interfaces are numerous and trival
Better to throw away many of these
Mocked specs are more brittle
55. References
The RSpec Book - David Chelimsky et al
xUnit Patterns - Gerard Meszaros
Mocks Aren't Stubs - Martin Fowler
Mock Roles, not Objects - Steve Freeman
et al
56. Contact
Slides prepared by Ashley Moran
ashley.moran@patchspace.co.uk
www.patchspace.co.uk
I'm available for training/consultancy in
Ruby and RSpec on a freelance basis
I code for food