Giter Club home page Giter Club logo

stubadub's Introduction

stubadub

A small stubbing library for Clojure and ClojureScript.

To quote Kris Jenkins in his Which Programming Languages Are Functional? blog post:

Seen through the lens of side-effects, mocks are a flag that your code is impure, and in the functional programmer's eye, proof that something is wrong.

So yeah, you should treat stubbing your code much like stubbing your toe: It's painful and you should strive to avoid it.

Sometimes tho, the code you're testing needs to do some side-effecting. Or maybe all the code you're maintaining isn't a dreamy pure function landscape.

In that case, feel free to use stubadub.

Install

Add [stubadub "2.0.0"] to [:profiles :dev :dependencies] in your project.clj.

Breaking change in 2.0

The old :returns-by-args has been rechristened :return-fn. The former took only maps, while the latter can be any function. Its use with maps is unchanged, apart from the name.

Usage

(ns example-test
  (:require [stubadub.core :refer [with-stub calls-to]]))

with-stub takes a function symbol and replaces it in the scope of its body. Use calls-to to return the list of calls to the stub.

Like this:

(with-stub spit
  (spit "test1.txt" "not written to disk")
  (spit "test2.txt" "not written to disk either")
  (calls-to spit))

;; => (("test1.txt" "not written to disk")
;;     ("test2.txt" "not written to disk either"))

You can specify a return value for the stub with :returns:

(with-stub slurp :returns "not read from disk"
  (slurp "test3.txt"))

;; => "not read from disk"

Also, you can supply a function to produce the desired return value with :return-fn. The supplied function will be called with a vector containing the arguments of the stubbed function:

(with-stub slurp :return-fn (fn [[file _ _]] (str file " not read from disk"))
  [(slurp "test4.txt" :x :y)
   (slurp "test5.txt" :y :z)])

;; => ["test4.txt not read from disk" "test5.txt not read from disk"]

Since the arguments to your function are supplied in a vector, and Clojure maps indeed are functions themselves, you can conveniently supply a map of arguments to return value:

(with-stub slurp :return-fn {["test4.txt" :x :y] "not read from disk"
                             ["test5.txt" :y :z] "not read from disk either"}
  [(slurp "test4.txt" :x :y)
   (slurp "test5.txt" :y :z)])

;; => ["not read from disk" "not read from disk either"]

And you can nest several stubs, at which point you're probably not a happy person:

(with-stub spit
  (with-stub slurp :returns "not read from disk either"
    (spit "test4.txt" (slurp "test5.txt"))
    (calls-to spit)))

;; => (("test4.txt" "not read from disk either"))

Usage from ClojureScript

Replace

(:require [stubadub.core :refer [with-stub calls-to]])

with

(:require [stubadub.core :refer [calls-to] :refer-macros [with-stub])

A word of warning

Since stubadub uses with-redefs under the hood, your stubs are not thread-local. This means that parallell tests are out. Open an issue if this is a blocker for you, and we can look at making a set of thread-local functions.

Contributors

  • Anders Furseth added :return-fn and fixed a bug with using stubadub across threads.

Thanks!

Contribute

I mainly consider this library complete, but if you have a wonderful addition to the library, please don't let that stop you. :)

Remember to add tests for your feature or fix tho, or I'll certainly break it later.

Running the tests

Run tests with

lein test

Run tests automatically on changes with

lein test-refresh

Make sure to run the tests for ClojureScript as well:

lein doo node

You'll have to have the node binary installed.

License

Copyright © 2016 Magnar Sveen

Distributed under the Eclipse Public License, the same as Clojure.

stubadub's People

Contributors

duckyuck avatar magnars avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.