This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-05-17
Channels
- # announcements (10)
- # aws (10)
- # babashka (11)
- # beginners (77)
- # calva (9)
- # cider (10)
- # cljdoc (7)
- # cljs-dev (47)
- # clojure (47)
- # clojure-uk (4)
- # clojurescript (87)
- # community-development (15)
- # conjure (14)
- # core-async (25)
- # cursive (6)
- # fulcro (6)
- # helix (3)
- # joker (2)
- # nrepl (1)
- # off-topic (1)
- # pathom (9)
- # pedestal (6)
- # re-frame (22)
- # reitit (15)
- # shadow-cljs (26)
- # spacemacs (16)
- # testing (2)
- # tools-deps (12)
- # uncomplicate (10)
- # xtdb (22)
I am porting a clojure project over to a new framework and I’m getting Unable to resolve symbol: inst-ms
when trying to run a repl. Why would that be, it’s part of clojure.core no ?
Likely your project is not explicitly specifying what version of clojure it wants you you just end up running with anything, and something is causing that to be an old enough version of clojure that inst-ms doesn't exist
i see there's a call to push-thread-bindings
in tools.deps.alpha without an associated call to pop-thread-bindings. this would be worrying except the person who wrote this code is also possibly the one who wrote the docstring of push-thread-bindings to never use it without the pop. Its on a fixed thread pool executor service so it seems like it should slowly be poisoning the threads?
i'm wondering what i'm missing. i figured if the threads could die it wouldn't matter but these are in a pool so presumably they are just in a bad state after its first use?
(defn submit-task
^Future [^ExecutorService executor f]
(let [bindings (get-thread-bindings)
task #(do
(push-thread-bindings bindings)
(f))]
(.submit executor ^Callable task)))
Probably should be a pop, but the bindings being pushed in in each case are replacing the previous so there’s no functional issue
Just memory leak, but not one big enough to be noticed typically
No worries
What is the canonical way to test state in Clojure? Assuming you have some atom that contains the app-state and there are a bunch of handlers that manipulate it and you want to test the handlers, do you use with-redefs to set the app-state?
I tend to do it like this:
(def global-state (atom ...))
(defn handler [{:keys [state]
:or {state global-state}}]
...)
the idea being, I can test handler
isolatedly, passing an atom as an arg.
Same for each handler - I test them individually, without having to set up something more elaborate.
with-redefs
is not exactly clean (for one thing it's not thread-safe, if you were to run tests in parallel)
@U45T93RA6 - thanks, injection was the other option
The broader question is, mock function or mock state?
Personally I tend to do both. For example a test-only protocol implementation ("mock function") could write to an atom ("mock data") At the same time I consider mocking some sort of last resource - the idea being to favor hitting pure functions instead
agreed. Though, when one tests a stateful application it is almost impossible to avoid either setting state up or mocking some function
There’s a certain class of bugs that are entirely based on how state is setup and with Clojure, it seems a lot easier to test state than it is in other systems where state is spread across objects or other such systems
an alternative (or at least addition) that comes to mind is doing heavy validation of state in all relevant/possible places e.g. for an atom, use :validator or place :pre in defns asserting that the received state is valid and consistent of course most web apps aren't atom-based, but it's a trick I occasionally use This way, one doesn't necessarily write state-related tests, but instead writes higher-level tests (a user story) and relies in the preconditions being exercised
Yeah, I was just discussing this with someone and we arrived upon spec + state based tests being a pretty solid guard
regarding mocks / with-redefs, the more reliable option is to make update functions that simply take a map and return a map, you test them by offering a map and inquiring about the map that comes back
then, in the actual app, you can use that function as an arg to swap!
, but there's no need to attach the state update to the state management code
@U051SS2EU - fair, but how would you test the fn that’s calling swap!
?
by giving it different (limited and testable) functions to call, or limit tests of that function to full integration tests
I would consider it a code smell if the swap! call is nested deep - I expect global effects and mutation to happen at the top of the stack if it needs to happen
(aside from debugging etc.)
Yeah, all the swap! calls here are only in the handlers of a server
The general popular option to test db integrations etc tends to be to pull out a protocol and test it with something reified
with app state, as you say, unit test the individual fns that work on the fragments of the global object and then write integration tests on the swap!/reset! calls to it
yeah, so if your api is atom + fn + swap! your "reified object" is just a simple function
or going the other way, for testing an individual handler, the "test harness" is just a data literal
I’m doing something like this at the moment
(with-redefs [d/user-present? (constantly true)]
(let [response (s/signup (-> (mock/request :post "/signup/boo")))
body (:body response)]
(t/is (= 200 (:status response)))
(t/is (= "Already signed up" body))))
Anyone has https://github.com/lambdaisland/deep-diff2 set up against clojure.test? For comparing expected vs actual
I reckon it's not too hard to accomplish, I'm just curious if someone has a polished defmethod
snippet already
currently I grab the expected and actual vals by hand and paste them against a diff
invocation that I have as an IDE snippet
Not too cumbersome, but of course a built-in integration would be nicer
Yeah I can dive into it :) but other than that I tend to be careful around the idea of depending completely in an alternative runner.
Same for eftest
. Both projects rock tbh, but tests are too important for me to make a migration without some prior study
first time trying to use clojure and i'm looking to set up vim+clojure-lsp. i've cloned a github project to test this out with, but clojure-lsp is giving me an unknown symbol for just about everything in this file: https://github.com/andeemarks/shokunin-august/blob/master/src/shokunin/august.clj. is this because of the clara.rules macros?
@cantdoart5 yes that’s very likely. static analysis struggles with macros that implicitly provide/allow symbols inside their body
thanks, @lilactown for the insight
what's the idiomatic way to take a vector like [:a "A" :b "B"]
and get a map like {:a "A" :b "B"}
? I think I want something like (into {} (something v))
but I can't remember the something
I'm looking for 🙂
One way:
user=> (def v1 [:a "A" :b "B"])
#'user/v1
user=> (apply hash-map v1)
{:b "B", :a "A"}