00:00:10.080
my name is BOS blim and today I'm going
00:00:12.840
to talk to you about webm uh Ruby Jam
00:00:15.799
for mocking HTTP requests so first a
00:00:20.160
little bit about
00:00:21.720
me um I've been developing software for
00:00:25.199
over 20
00:00:26.640
years and back in 2006 when I I was
00:00:30.199
still a happy Java developer a friend of
00:00:33.120
mine Andre chivda came to me and said
00:00:35.520
hey have you heard of that language
00:00:37.280
getting popular called
00:00:38.840
truby and he sent me a link to that book
00:00:42.719
uh I have seen a few copies
00:00:44.800
yesterday and my life as a programmer
00:00:49.120
has changed forever and I've been using
00:00:51.440
kby ever
00:00:53.280
since um I live in
00:00:55.640
waro um but I work remotely since for
00:01:00.280
that was
00:01:01.559
popular and I'm the author and the
00:01:05.720
single maintainer of
00:01:09.200
webm um it's not the first year that I'm
00:01:13.280
presenting about
00:01:14.520
webm my previous presentation was back
00:01:17.759
in
00:01:18.640
2009 that's me back in
00:01:21.360
London um and I decided to do an
00:01:25.560
extrapolation of my
00:01:28.000
presentations and I estimate that the
00:01:30.520
next year I'll be presenting about webm
00:01:32.159
Mo it's
00:01:34.320
2039 so you have a unique chance to
00:01:36.680
learn something about webm Mo
00:01:40.439
today okay so uh what webm is for first
00:01:45.280
webm allows you to stop HTTP requests
00:01:48.799
but what does it mean it allows you to
00:01:51.159
declare fake responses so that when your
00:01:55.520
Ruby application makes an HTTP request a
00:01:59.280
fake response will be returned instead
00:02:01.920
of making a real HTTP
00:02:04.719
connection and it also allows you to
00:02:07.840
verify that request has been executed
00:02:11.360
whether that was a sted request or a
00:02:13.840
real
00:02:15.200
request the idea is not original there
00:02:17.879
was a gem called fake web before but it
00:02:22.120
was not sufficient to my needs therefore
00:02:24.599
I decided to create my own solution and
00:02:28.400
I created webm the first version
00:02:30.680
during a one day company
00:02:33.360
hakon and what's important I created
00:02:36.720
webm to address my own needs as a ruby
00:02:40.440
developer and this needs happen to be
00:02:43.360
the needs of many other Ruby
00:02:45.840
developers and hence webm has been
00:02:48.519
downloaded more than 270 million
00:02:52.000
times uh it has almost 4,000 stars on
00:02:55.480
GitHub um if you haven't started yes yet
00:02:58.640
please do I'm aing for
00:03:01.400
four um over 260 people
00:03:05.440
contributed uh to webm Mo over the last
00:03:10.159
15 years uh John Gallagher just
00:03:13.720
yesterday thank
00:03:15.440
you um and yeah including Ki so a few
00:03:20.080
months ago Sam saffron the co-founder of
00:03:22.879
this course submitted a poll request to
00:03:25.400
webmo and he included a transcript of
00:03:27.920
his conversation with Chad GPT
00:03:31.400
fortunately CH GPT was completely
00:03:33.640
useless in that case therefore we as
00:03:36.000
human Ruby developers are still
00:03:39.480
safe um webm is used by thousands of
00:03:42.480
projects on GitHub and it's a dependency
00:03:45.400
of thousands of uh registered Ruby
00:03:49.400
jams um here are some of the popular uh
00:03:53.920
Ruby projects that depend on webmock and
00:03:57.519
if you haven't had a chance to use any
00:04:00.360
of them then you probably used this
00:04:05.040
one uh webm also inspired programmers in
00:04:08.799
other languages who created similar
00:04:13.680
Solutions okay so uh what does webmock
00:04:17.799
offer well first it gives us this nice
00:04:22.160
DSL uh that allows us to write a clean
00:04:25.639
code uh to stop HTTP requests
00:04:30.800
and it also gives us nice DSL to verify
00:04:33.440
that requests have been executed and
00:04:36.520
what's important is that both the of
00:04:38.360
these dsls are HTTP client Library
00:04:41.240
agnostic so once you write it you can
00:04:44.360
use it with any HTTP client or switch
00:04:46.759
HTTP clients without modifying your
00:04:51.000
tests uh webm follows stab execute
00:04:55.039
verify Paradigm which I borrowed from a
00:04:59.039
Java test framework called
00:05:01.160
mitao um and slightly different to what
00:05:04.080
for example you can get used to with
00:05:06.080
rspec what a single X declaration both
00:05:09.400
creates the Stop and creates the
00:05:13.840
expectation uh here this two steps are
00:05:16.400
separated but it allows us to stab
00:05:19.759
request without verifying that they have
00:05:21.600
been executed or verify real request
00:05:24.639
without stubbing
00:05:27.319
them uh webm also allow allows us to run
00:05:31.440
call backs after each
00:05:34.080
request and this can be for example used
00:05:37.080
for recording requests that have been
00:05:44.759
executed um webm offers many features
00:05:47.600
when stabbing so you can stop your
00:05:49.400
request to time
00:05:51.440
out or you can stop request with basic
00:05:57.360
authentication or you can even record
00:06:00.319
row responses with Carl and then declare
00:06:03.400
stabs that will return this row
00:06:08.280
responses um webm supports all popular
00:06:11.240
HTTP clients in
00:06:14.120
Ruby and it's supports all popular
00:06:17.240
testing
00:06:19.680
Frameworks okay so we know what are the
00:06:23.000
basic features of webm but you might ask
00:06:25.039
why mocking HTTP requests in the first
00:06:27.120
place
00:06:28.120
right so first first it allows you to
00:06:31.360
run your test in isolation without an
00:06:34.319
internet connection so if you came here
00:06:37.440
uh by plane like me and you wanted to
00:06:39.919
work on the plane uh webm is a perfect
00:06:43.440
solution you can run your test without
00:06:44.880
actually having access to an external
00:06:48.080
API um it also allows you to avoid
00:06:51.840
accidental changes to third party apis
00:06:53.880
for example if you incorrectly configure
00:06:55.840
your development or test environment
00:06:57.680
with production credentials
00:07:00.160
no changes will be made webm will
00:07:02.440
prevent
00:07:03.680
that um webm also allows you to run your
00:07:07.080
test reliably so even if you have a weak
00:07:10.400
internet connection or a third party API
00:07:14.080
is currently down your tests will still
00:07:19.039
run and the tests are fast because
00:07:21.800
you're not depending on the current
00:07:23.639
Internet connection or the fact that
00:07:25.560
third party API is currently busy and
00:07:28.520
and the respons are
00:07:30.919
delayed and you can test all possible
00:07:33.720
scenarios all edge cases you can test
00:07:36.240
timeouts uh you can test 500 400
00:07:41.840
responses and all this setup is done in
00:07:45.599
Ruby so there is no need to make some
00:07:48.919
setups remotely on a third party
00:07:52.680
API but mocking HTTP can be useful also
00:07:57.440
in other environments that test
00:08:00.840
environment so for example you can
00:08:03.960
develop without having an internet
00:08:06.120
connection just you just need to declare
00:08:08.240
some steps put them into a race
00:08:11.759
initializer if it's a race application
00:08:14.680
and you can run uh you can develop your
00:08:18.319
app without having an internet
00:08:19.599
connection on a plane uh you can also
00:08:23.879
manually test your application and test
00:08:26.520
various scenarios so you can test how
00:08:28.479
your app will behave if a remote API
00:08:31.400
times out or returns 500
00:08:34.560
response um and you can also develop
00:08:37.479
without actually having access to an
00:08:39.360
external API so there was a project once
00:08:41.959
that I worked on that heavily relied on
00:08:44.600
a third party API and yet we haven't
00:08:47.399
received access to that API for about
00:08:49.440
one and a half month so what we have
00:08:52.080
done we read the specification and
00:08:54.000
documentation of that API we created
00:08:56.279
some request stabs put them into race
00:08:59.880
initializer and we're ready to go we
00:09:02.640
developed and you can do the same in
00:09:04.720
staging environments to demo the
00:09:06.640
features that we have
00:09:09.839
implemented um so this is how a sample
00:09:14.200
uh race initializers with
00:09:16.279
some uh with some request tabs can look
00:09:22.839
like okay so we know that mocking HTTP
00:09:26.680
requests can be useful sometimes uh um
00:09:29.839
but why webm why would you use webm
00:09:31.720
instead of creating your own solution or
00:09:33.880
stubbing maybe HTTP client methods
00:09:38.440
directly um so let's say you have this
00:09:42.160
kind of code in your application and
00:09:45.640
you're expected to change it to modify
00:09:47.760
the
00:09:48.880
functionality um so what do you do first
00:09:51.920
well we want to do things properly we
00:09:54.440
want to do things as first so first we
00:09:56.920
find the corresponding test so we find
00:09:59.600
the test and we find that Associated
00:10:03.519
complicated setup so what do we do first
00:10:07.519
what I would do is probably I would do G
00:10:10.040
blame and check who wrote that
00:10:11.920
complicated
00:10:13.120
code just to realize yeah it was me a
00:10:16.040
few years
00:10:17.720
ago um and then I would import webm and
00:10:21.120
replace that complicated
00:10:23.200
setup with webmock
00:10:26.519
DSL and now that I have a clean readable
00:10:29.920
test I can modify the code so for
00:10:32.160
example I can also change the code to be
00:10:34.839
more readable by replacing net HTP with
00:10:38.079
htpr RB which also gives us this nice
00:10:45.800
DSL um webm is perfect for test driven
00:10:50.120
development because of webm DSL you can
00:10:53.399
focus on the functionality on testing
00:10:56.399
the the the behavior not the implement
00:10:59.680
so you can write your tests first
00:11:01.240
without even deciding what HTP client
00:11:03.839
you're going to use or what methods on
00:11:06.880
that HTP client Library you're going to
00:11:11.040
call uh but webm is also very useful for
00:11:14.160
legacy application so usually what I
00:11:15.760
will do uh when I
00:11:18.639
inherit uh some uh Legacy Ruby
00:11:22.160
application I'll will import webm and
00:11:24.639
now I'm safe I can run my tests I can
00:11:27.519
run a development without risking
00:11:29.880
that the app is going to make an
00:11:31.519
unexpected request to a third party API
00:11:34.120
and if it does webm will not will let me
00:11:37.399
know about
00:11:39.120
this um webm allows us to
00:11:42.880
stop uh your unescaped versions of the
00:11:45.880
Euros so for example I find this code at
00:11:48.800
the bottom way more readable than the
00:11:50.600
one in the
00:11:53.839
middle um and the feature I really like
00:11:57.000
about webm is that if you declare your
00:12:00.440
stop incorrectly or uh the stop is
00:12:04.079
actually correct but the request is
00:12:05.920
incorrect webm will stop the
00:12:09.600
request and will'll provide you with
00:12:12.000
this nice instructions on how this
00:12:15.920
request is expected to be stopped so you
00:12:18.399
can just copy and paste it into your
00:12:20.320
test
00:12:23.720
setup so basically webm exists to make
00:12:29.600
our lives
00:12:31.240
simpler uh but with that
00:12:34.959
Simplicity with that DSL there is a cost
00:12:38.040
the cost of not knowing what actually
00:12:40.360
happens
00:12:41.720
underneath and that might feel like
00:12:45.160
magic a
00:12:46.639
bit and a few months ago I went
00:12:52.160
to chavier presentation where he
00:12:55.880
explained
00:12:57.320
how uh tid work Works
00:13:00.040
internally and that got me inspired and
00:13:02.440
I thought I'll do the same I'll explain
00:13:04.360
how webm Mo Works
00:13:08.279
internally but in order to understand
00:13:10.560
how webm Works internally we first have
00:13:12.760
to understand how HTTP clients
00:13:16.199
work
00:13:17.760
so let's take a sample uh HTTP clients
00:13:21.880
the typical client will usually provides
00:13:25.000
an API uh which consists of some public
00:13:28.399
methods
00:13:29.639
that usually represent HTTP
00:13:32.839
verbs uh but these public methods
00:13:34.880
usually do not do
00:13:37.399
much uh so we can use them like
00:13:44.399
that but yeah usually they don't do much
00:13:48.000
there is usually some method or set of
00:13:52.000
methods that do all the heavy lifting
00:13:54.560
underneath so let's call this for
00:13:57.000
example let's call this method handle
00:13:58.560
request
00:14:01.680
so what this handle request method
00:14:03.839
usually will do is it will first gather
00:14:06.639
all the parameters that you have passed
00:14:08.560
and it will build the request
00:14:11.399
object and then it will send the request
00:14:15.720
over HTTP or uh sorry TCP or SSL
00:14:20.240
connection and upon receiving the
00:14:22.279
response it will build the response
00:14:25.800
object and if the uh HTP Library client
00:14:30.480
supports middleware it might also run
00:14:33.160
some
00:14:37.720
middleware okay so now now that we
00:14:40.720
understand how typical HTTP client works
00:14:43.279
we can understand how web Works
00:14:46.079
internally so first stabby so when you
00:14:50.440
do a stab declaration like that what
00:14:53.000
webm will do underneath is it will
00:14:55.680
create a request stop object
00:14:59.680
and that request T object will be then
00:15:03.120
registered in the global request T
00:15:10.040
registry and request T object consist of
00:15:13.839
two attributes so one is request pattern
00:15:17.279
and request pattern contains all
00:15:18.759
information required to match the
00:15:22.000
request associated with that stuff and
00:15:24.959
then it has a set of fake responses that
00:15:29.360
are expected to be returned when a
00:15:31.279
matching request
00:15:33.079
appears and what's important is that the
00:15:36.399
sub request method Returns the stab
00:15:38.880
itself which allows us to chain it with
00:15:42.519
some additional calls so we can call it
00:15:45.199
with the width method and the width
00:15:49.079
method is to extend the request pattern
00:15:54.040
so we can add additional criteria to
00:15:56.519
match the request
00:15:59.279
and again we are returning request St
00:16:01.240
object which allows us to chain it with
00:16:03.639
the to return method and to return
00:16:06.519
method adds a fake response to that stop
00:16:10.480
so when a request will be made matching
00:16:13.000
that request stop matching the request
00:16:15.199
pattern this declared fake response will
00:16:17.639
be
00:16:19.519
returned um request call backs um what
00:16:24.920
will happen if you call after request
00:16:27.000
webm will take this blog and register is
00:16:30.000
in the global request
00:16:35.440
registry
00:16:37.680
so we have we now have this Global stuff
00:16:41.600
registry we have the request stops we
00:16:45.199
have some call backs but still nothing
00:16:47.800
happens right so the if I now make an
00:16:50.160
HTTP request it won't be
00:16:53.560
affected and so what
00:16:56.800
actually does the work and intercept
00:16:59.360
this
00:17:00.399
request is in webm are the adapters so
00:17:05.000
webm has an adapter for each
00:17:08.039
HTTP Library so it will be a separate
00:17:12.079
adapter for curve or separate for net
00:17:16.280
HTTP um so to understand how an adapter
00:17:19.640
work like Works let's create a sample
00:17:22.959
adapter for our sample HTTP
00:17:27.120
client um so what an adapter will do it
00:17:31.480
will create a copy of a class that
00:17:35.360
contains our handle request method that
00:17:38.760
has all the heavy lifting it will create
00:17:41.039
that copy by sub
00:17:42.559
classing and then it will start monkey
00:17:46.440
patching that handle request method so
00:17:49.960
first it will after the request is built
00:17:54.240
webm will create the request signature
00:17:58.080
and the request sign signature contains
00:18:00.080
all necessary information to match the
00:18:02.880
request against the request
00:18:05.520
pattern and this request signature will
00:18:08.799
be registered in request
00:18:13.400
registry and then if there is a stop
00:18:16.520
found that matches that request
00:18:19.600
signature webm will return any declared
00:18:22.600
fake responses otherwise a real request
00:18:26.120
will be made
00:18:29.640
but yeah webm by default prevents all
00:18:33.200
real HTTP requests so in addition of
00:18:36.880
that it also has to check whether a real
00:18:38.799
request is allowed if it's allowed a
00:18:41.400
real request will be made and a real
00:18:43.760
response will be returned otherwise
00:18:46.080
webmock will return will raise an error
00:18:50.000
and after that error you will be
00:18:52.039
presented with this nice stubbing
00:18:56.320
instructions um after that if there are
00:18:58.880
callbox
00:18:59.919
registered uh webm will run them if
00:19:03.520
there is an middleware supported by the
00:19:06.280
HTTP client uh it will be run and then
00:19:09.880
uh response will be
00:19:12.520
returned so to recap request is built
00:19:15.760
then we build request signature and
00:19:17.679
register it in the request registry then
00:19:21.159
if there is a stop matching that request
00:19:23.200
we return a fake
00:19:24.760
response otherwise we check whether it's
00:19:27.960
allowed to make a real request and we
00:19:30.320
make it if not we raas an exception and
00:19:35.679
the nice instructions are
00:19:37.640
printed um the callbo are run middle one
00:19:42.000
is Middle Way is run and then uh
00:19:44.520
response is
00:19:45.840
returned so this is how an adapter Works
00:19:49.400
um okay but just by creating this copy
00:19:53.360
uh this monkey par copy of a clients uh
00:19:57.200
of this class still nothing happens
00:19:59.480
right if I call sample HTP client get
00:20:02.559
still a real class will be
00:20:05.120
used so we have to do something more so
00:20:08.120
what webm will do it will create first
00:20:10.360
create a reference uh to that original
00:20:14.320
uh to that original class and then it
00:20:17.240
will replace the original class with our
00:20:21.600
modified class with our monyer class by
00:20:23.799
using constant replacement
00:20:32.679
so yeah and uh and while this
00:20:37.760
solution uh you know might not sound
00:20:40.880
nice because we're doing Monkey patching
00:20:42.799
right and monkey patching is bad I quite
00:20:45.960
like it because we are not modifying the
00:20:48.159
original class we are just modifying the
00:20:49.840
copy and at any point we can call webm
00:20:52.400
disable and we can revert to the
00:20:54.200
original
00:20:57.360
state so so now when we call webm enable
00:21:00.960
all adapters will be enabled the created
00:21:04.520
copies of original classes will be
00:21:06.720
created and then Originals will be
00:21:09.080
replaced now when I call stop request a
00:21:12.640
request stop will be registered in
00:21:14.960
request
00:21:16.159
registry then when I call when I make
00:21:18.919
the real when I make the request a fake
00:21:22.279
response from the stuff will be
00:21:24.919
returned but now we can do something
00:21:27.400
more uh um so if you remember the
00:21:30.080
request signatures that we registered in
00:21:32.000
the request registry we can now verify
00:21:35.559
that request can actually been
00:21:46.000
made okay
00:21:49.360
so this is how web mock works as you can
00:21:53.559
see there is no magic this is just brute
00:21:57.840
monkey patching
00:22:01.080
um
00:22:03.200
and as I told you
00:22:05.679
earlier webm Mo I created webm Mo to
00:22:09.520
address my own needs as a ruby
00:22:12.880
developer but there was also another
00:22:15.720
factor that greatly affected me and
00:22:20.440
greatly influenced me to create
00:22:23.320
webm and that factor was
00:22:27.240
people so so back in
00:22:30.720
2009 when I created webm I lived in
00:22:33.279
London and I worked for a company called
00:22:35.760
new
00:22:36.720
bamboo and new bamboo was a team of very
00:22:41.400
passionate
00:22:43.600
developers
00:22:45.400
we inspired each
00:22:47.679
other we supported each other we shared
00:22:50.440
our passion for
00:22:51.960
Ruby uh we encourage each
00:22:55.039
other and during my 20 years of building
00:22:58.600
software
00:23:00.480
the thing I have learned is that the
00:23:03.640
most important factor for your growth as
00:23:06.320
a developer is the people you work with
00:23:09.559
and what you learn from
00:23:11.799
them therefore
00:23:14.600
when L stal said this
00:23:17.679
words I took it as a
00:23:20.840
compliment because to me Ruby was not
00:23:25.400
always not only about the nice syntax
00:23:27.760
not only about
00:23:30.039
it was always mainly about the
00:23:34.080
people the people who shared their
00:23:37.799
passion the people who are friendly to
00:23:40.400
each
00:23:41.760
other the people who Inspire each other
00:23:44.880
like on events like
00:23:47.919
this and people who are nice to each
00:23:51.600
other and I am really happy that I can
00:23:56.279
celebrate with all of you are passion
00:23:59.080
for Ruby
00:24:01.360
today thank you