ElStevo
ElStevo

Reputation: 71

How to fake nested use of third-party APIs involving potentially dangerous actions?

I have three services in a Clojure application:

I need to write integration tests for Service C that do not call out to the third-party, as they provide neither a set of testing endpoints nor a way to reverse my changes.

The two options I see are:

I am somewhat new to testing in functional languages, so it's more than possible that I'm missing something obvious.

Upvotes: 0

Views: 249

Answers (3)

Stefan Kamphausen
Stefan Kamphausen

Reputation: 1665

If I understand your use-case correctly, I'd avoid calling out to Service A in my integration tests for Service C by mocking the whole Service A with clj-fake-http. I've used that library very happily in one of my work projects and can highly recommend it.

This assumes that Service A is actually a different process that you're talking to. Should Service A live in the same process as Service C you might as well mock away the calls to the 3rd party API that Service A does.

Upvotes: 1

Denis Fuenzalida
Denis Fuenzalida

Reputation: 3346

If you know some details about the implementation of the services, and those are mostly written in Java, you can use proxy to create an alternate implementations of the classes or interfaces that you want to constraint during the tests.

An example would look like:

(let [proxy-a (proxy [com.dangerous.ServiceA] []
                (launchMissiles [x y z]
                  (log/info "Phew! we didn't fire a missile during tests!")))

      proxy-b  (proxy [com.example.ServiceB] []
                 (callServiceA [x y z]
                   (.launchMissiles proxy-a x y z)))

      proxy-c (proxy [com.example.ServiceC] [x]
                (callServiceB [x]
                 (.callServiceB proxy-b x 1 2)))]

     ;; Perform a test on the outer proxy with:
     (.callServiceB proxy-c "testing!")

More details here: https://clojuredocs.org/clojure.core/proxy

Upvotes: 1

Alan Thompson
Alan Thompson

Reputation: 29958

Use option #2, but with-redefs (there is almost never a need for with-redefs-fn. See

Example:


(ns http)

(defn post [url] ; dummy fn for testin
  {:body "Hello world"})

(ns app
  (:require [clojure.test :refer [deftest is run-tests]]))

(deftest is-a-macro
  (with-redefs [http/post (fn [url] {:body "Goodbye world"})]
    (is (= {:body "Goodbye world"} (http/post "http://service.com/greet")))))

(run-tests) ;; test is passing

Upvotes: 0

Related Questions