This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-02-08
Channels
- # aleph (5)
- # announcements (3)
- # aws-lambda (16)
- # babashka (17)
- # beginners (59)
- # calva (168)
- # clerk (4)
- # clj-kondo (62)
- # clojure (77)
- # clojure-belgium (4)
- # clojure-brasil (10)
- # clojure-ecuador (3)
- # clojure-europe (41)
- # clojure-losangeles (2)
- # clojure-nl (2)
- # clojure-norway (24)
- # clojure-uk (2)
- # clojurescript (44)
- # clr (21)
- # community-development (7)
- # conjure (1)
- # cursive (3)
- # datalevin (15)
- # datomic (1)
- # deps-new (12)
- # emacs (45)
- # events (1)
- # fulcro (8)
- # funcool (7)
- # graphql (5)
- # hugsql (15)
- # jobs (2)
- # matcher-combinators (17)
- # meander (14)
- # membrane (31)
- # pathom (28)
- # pedestal (6)
- # practicalli (6)
- # re-frame (12)
- # releases (1)
- # remote-jobs (1)
- # shadow-cljs (32)
- # tools-deps (8)
- # vim (16)
How could I mock an HTTP request in a Unit Test? As I googled and found https://github.com/ring-clojure/ring-mock, but I’m not sure it’s the correct one to use.
Here is the code I want to mock: There’re two HTTP requests which I’d like to mock, fetch-volcanic-user-by-id and get-candidate-by-email since they might be 404, I’d like to protest the login with Unit Tests.
I usually don't "mock" it, easy enough to spin up a real http server and hit it in tests
Yes, I did the same as you. But I’m worried that some month later, I’ll forget any edge cases I added today, or when I refactor this block of code, I’ll break it, then it’s better to protect them with Unit Tests.
There are a number of things you can do to make this code easier to unit test. For example, you could pass in the two functions that make the HTTP calls -- then you can pass in "mock" functions in the tests and have it call those instead.
I mean, I have a deftest in my test suite, and within the deftest I start the webserver, interact with the server via http and make assertions about the results, then stop the webserver
You could also split the "volcanic" part from the "candidate" part so you have two smaller functions to test.
> within the deftest I start the webserver… Oh, it’s my bad. In the code block above, I do real HTTP requests, as I’m not building a server with API to test. Actually, I’m working on a script which fetches different resources remotely and then does some logic.
Right, but hiredman was suggesting spinning up "mock" servers in your test to call into (instead of the actual services). Which is what we do at work (we work together).
It depends what level you want to mock things at and why.
(in other words, there's no one right way to do this 🙂 )
Oh, I see.
And could you suggest me some tutorials for setup a “mock” servers locally?
About the level, I think I’m not clear about it
Hmm, no idea about that, sorry.
(Hiredman and I have both been doing Clojure for a decade so we're not so good at recommending beginner-level tutorials, unfortunately!)
Longer than that :)
Time flies, but it’s gotta be closer to 13 right?
Haha... yeah, probably... I think we both got started in 2010?
@U04V70XH6 yup that sounds right
LoL, and thank you both again, as I learned a new level to test my code - setup a “mock” server, then I can test them locally without touching the internet.
@U04GM4FRG13 there is one idea, http libraries will each have their own ways of testing themselves, so you can poke at their tests to see what they’re doing
Or if they’re kind then they’ve documented an approach for you as above
Documentation in general and tutorials in particular have changed a lot in that time. Hopefully for the better.
@U04GM4FRG13 my favorite style is when a library lets you plug in some sort of “backing store”, and you can use the real network client in prod, and then an atom, say, in tests
With that kind of design, you can set up the “server” using a hash map in an atom, do your stuff and then check the mutated value afterward (or for GET tests check that you get out what you populated the map with)
make sense. It’s the best way to have two different access behaviour between the prod and local.
Here is the code I want to mock: There’re two HTTP requests which I’d like to mock, fetch-volcanic-user-by-id and get-candidate-by-email since they might be 404, I’d like to protest the login with Unit Tests.
is it possible to evaluate that I have removed a function
Do you mean something like you have performed (undef foo)
and you want to ensure that foo
is no longer bound to any value?
Ugh, sorry, no morning coffee yet. There is no such thing as undef
.... Not sure where my brain got that.
Here is a short REPL session in Clojure/JVM that might show pieces that lead you to what you are looking for:
user=> (def foo 1)
#'user/foo
user=> foo
1
user=> (contains? (ns-map 'user) 'foo)
true
user=> (get (ns-map 'user) 'foo)
#'user/foo
user=> (ns-unmap 'user 'foo)
nil
user=> (contains? (ns-map 'user) 'foo)
false
If. you want something similar in ClojureScript, (a) I'm not sure if it is possible, and (b) I'm not familiar enough with the differences here between ClojureScript and Clojure/JVM to know the changes required
ns-unmap
is perhaps what you mean when you say "removed a function" ?
I assume that once you have a reference to a function you can call it until you release the reference.
(let[my-plus clojure.core/+] (my-plus 1 2))
Yes, but I would generalize that to "once you have a reference to any value, function or otherwise, you can still access/use that value until you have no references to it"
I mean I’d like to make sure that a function that I removed doesn’t get called. I changed the calling side too to not to call this function and perhaps the dangling function gets garbage collected at some point… So perhaps this is just uneccessary thinking.
Yes - the function will get garbage collected when the garbage collector runs and there are not references remaining to the function.
Functions take very little space in memory so probably not worth worrying about it from that perspective. If you want to be certain you can kill the REPL and start a new one.
I have one simple doubt, is that ok to do something like this?
"some text to describe something"
(defn somefn [a] a)
or should I always use comments?Rogue top-level strings don't make a lot of sense... Docstrings are generally a better construct when it comes to describing parts of code. Do you have an actual example? What would that text look like and what would it describe?
I did it by accident, not intentional, but the reader/compiler didn't complain, so it got me curious
You can any expressions at the top-level in a file. They will all be evaluated in order when the file is loaded.
You shouldn't have top-level forms that have side-effects however -- such as opening files, creating connections to things, making HTTP calls etc. Put those in functions (or at least in a delay
if you use a def
- but functions are better practice).
So a top-level string will be evaluated when the file is loaded and it has no side-effects so it is "harmless" but does cause code to be generated.
great explanation @U04V70XH6 thank you
@U04V70XH6 can you explain the “delay” bit? I have them def’ed but still see things kicking off or log output when I start my repl
(def thing (delay (some-side-effecting :expression)))
...
(defn some-fn [args]
... @thing ...)
☝️:skin-tone-2: Then the side-effecting stuff will only run the first time your defer thing
If you don’t like the ;; in some block you COULD also write #_”my string With newlines Etc”
Or (comment “…”)
But yes just use comments!