lein test выдает NPE для функции, использующей разрешение; работает в РЕПЛ

lein test генерирует исключение NullPointerException при тестировании функции, которая использует (resolve (symbol "a-fn")) для возврата функции a-fn. Тест работает нормально из REPL.

Мне не удалось найти способ решить a-fn в наборе тестов для leiningen, если это действительно проблема.

Я создал проект Leiningen под названием my-resolve by lein new my-resolve и добавил для них две функции и тесты:

источник/my_resolve/core.clj:

(ns my-resolve.core)

(defn a-fn [] "From a-fn")

(defn my-resolve [] (resolve (symbol "a-fn")))

тест/my_resolve/core_test.clj:

(ns my-resolve.core-test
  (:require [clojure.test :refer :all]
            [my-resolve.core :refer :all]))

;; Passes
(deftest a-fn-test
  (testing "a-fn"
    (is (= (a-fn)
           "From a-fn"))))

;; my-resolve-test behaves correctly in the REPL (the test passes,
;; returns nil) but throws a NullPointerException when called from
;; lein test.
(deftest my-resolve-test
  (testing "my-resolve"
    (is (= ((my-resolve))
           "From a-fn"))))

Спасибо.


person Graeme    schedule 15.03.2016    source источник


Ответы (1)


resolve делегирует ns-resolve с помощью динамически связанного *ns*, который в момент вызова в my-resolve.core/my-resolve будет другим в зависимости от того, из какого пространства имен он вызывается:

user=> (doc resolve)
-------------------------
clojure.core/resolve
([sym] [env sym])
  same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)

Я предполагаю, что в REPL вы вызываете my-resolve, когда в my-resolve.core ns. Когда lein test выполняет тест в my-resolve.core-test, *ns* динамически привязывается к (the-ns 'user) и этот ns (скорее всего) не содержит привязки к my-resolve.

person jgpc42    schedule 15.03.2016
comment
В примере a-fn и my-resolve кажутся параллельными в определении и тестировании, но это не так. lein test выполняет a-fn-test правильно. Как вы заставили lein test правильно выполнить my-resolve-test? - person Graeme; 15.03.2016
comment
Чтобы lein test выполнялось правильно, вам нужно изменить код в функции my-resolve на что-то вроде (ns-resolve 'my-resolve.core 'a-fn). - person jgpc42; 15.03.2016
comment
Превосходно. Что меня бросило, так это то, что мне нужно было указать пространство имен, в котором уже было определено my-resolve. - person Graeme; 15.03.2016