2013-10-28 4 views
1

Есть ли способ обмануть (не заглушить) функцию протокола с помощью Midje (clojure), используя что-то вроде «предоставленного» синтаксиса?Реализация замещающих протоколов в Midje

Это похоже на вопрос в: Mocking Clojure protocols, но с насмешкой.

Подробнее: У меня есть протокол и функция, которая возвращает что-то, что ее реализует. Я хотел бы заглушить функцию, чтобы вернуть макет протокола, и я хотел бы зарегистрировать ожидание одной из функций «реализации» издевавшегося протокола.

редактировать - вот пример:

Существует протокол и его реализация:

(defprotocol Thiny (go-bump [_ _])) 
(deftype TheThing [] 
    Thiny 
    (go-bump [_ _] 23)) 

Существует функция, которая возвращает реализацию протокола:

(defn gimme [] (TheThing.)) 

TheThing может быть DB или сетевым подключением или какой-либо другой неприятной вещью вы хотите избавиться от теста.

Тогда есть функция я хочу тест:

(defn test-me [n] 
    (let [t (gimme)] 
    (-> t (go-bump n)))) 

Я хочу, чтобы убедиться, что он называет гоу-врезаться с п.

Это моя первая попытка создать тест. Но это только наполовину сделано, я хотел бы ожидание установки на Thiny возвращаемых Дай мне:

(fact 
    (test-me 42) => 42 
    (provided (gimme) => (reify Thiny (go-bump [_ n] n)))) 

ответ

1

Для потомков. Вот рабочее испытание:

(fact 
    (test-me 42) => 42 
    (provided (gimme) => :the-thingy) 
    (provided (go-bump :the-thingy 42) => 42)) 

Хитрость заключалась в том, чтобы использовать несколько предоставленных утверждений, которые связаны друг с другом.

Wierd наблюдения. Тот же способ тестирования не работает для функции, которая использует другой синтаксис для вызова функций в протоколе. Не знаю, почему.

(defn test-me2 [n] 
    (let [t (gimme)] 
    (.go-bump t n))) 
+0

Хорошо, вы избегаете создания« диспетчерского объекта », некоторые из предложений по проблеме github были также насчет насмешек 'defrecord' –

+0

Это старый вопрос, но он по-прежнему актуальный. В Appareant вы не можете высмеивать функцию по протоколу, если вы также не издеваетесь над созданием объекта, который создает реализацию протокола. Или что-то типа того. –

1

Mocking протоколы не должны быть ничем не отличаются от насмешливого функция, которые необходимо учитывать, что первый параметр dispaching this, и поэтому функция издевательств должна учитывать этот тип.

Например, данный протокол P:

(defprotocol P 
    (foo [this]) 
    (bar-me [this] [this y])) 

Расширенная для типа Integer

(extend-protocol P 
    Integer 
    (foo [this] 
    (+ this 4)) 
    (bar-me [this] 
    (* this 5)) 
    (bar-me [this y] 
    (+ this y))) 

Вы можете проверить пару вещей, во-первых, нет никакой реализации для Long:

(foo 3) 
=> IllegalArgumentException No implementation of method: :foo of 
    protocol: #'P found for class: java.lang.Long 
    clojure.core/-cache-protocol-fn (core_deftype.clj:541) 

Работает как ожидается ints:

(foo (int 3)) 
=> 7 

Теперь определим этот факт и обеспечить функцию протокола, как вам нужно:

(fact 
    (foo (int 3)) => 7 
    (provided (foo 3) => 8)) 

В этом случае правильно не удается, так как насмешка возвращается 8 вместо 7 для указанного входа.

FAIL at (test.clj:20) 
    Expected: 7 
    Actual: 8 

Если значение издевается не достаточно, и вы должны предоставить альтернативную реализацию вместо этого, посмотрите на with-redefs-fn, вы можете обернуть тестируемые функции с ним.

=> (defn f [] false) 
=> (println (f)) 
;; false 
=> (with-redefs-fn {#'f (fn [] true)} 
#(println (f))) 
;; true 

Там также a discussion in GitHub about his с парой альтернатив во время выполнения диспетчерских издевается.

+0

Не уверен, что я понимаю, как это решает мою проблему. Мне нужно настроить ожидания на что-то, возвращаемое функцией. Обновлен мой вопрос с примера. – 4ZM

+0

Макеты среднего размера - это всего лишь данные, возвращающие макеты, вы указываете ожидаемый результат ввода, но не альтернативную реализацию, есть также проблема, которую окончательное значение 'given' получает во время компиляции, поэтому вы будете оценивать возвращаемое значение в отношении функция. –

+0

Оформить эту пару статей о mocks: http://www.agilogy.com/blog/tdd-in-clojure-with-midje.html, http://squirrel.pl/blog/2011/02/12/tdd- in-clojure-mocking-stubbing /, http://notesonclojure.blogspot.com/2010/06/mocking-with-clojurecontribmock.html –