Есть ли (идиоматический) способ тестирования результата функции ввода-вывода в Clojure?
У меня есть функция, которая сохраняет текст в файл:
(defn save-keypair
"saves keypair to ~/.ssb-clj/secret"
[pair file-path]
(let [public-key-string (->> (:public pair) (.array) (byte-array) (b64/encode) (bs/to-string))
secret-key-string (->> (:secret pair) (.array) (byte-array) (b64/encode) (bs/to-string))]
(spit file-path (str "Public Key: " public-key-string))
(spit file-path (str "\nPrivate Key: " secret-key-string) :append true)))
Он работает нормально (в настоящее время проверяет, просто открывая файл и просматривая его сам). Однако я хотел бы написать реальный тест, чтобы убедиться, что все работает правильно. Есть ли идиоматический способ сделать это в Clojure?
2 ответа
Изучите использование with-redefs
, как часть ваших модульных тестов. В вашем случае вы, вероятно, захотите объединить запись открытого и закрытого ключей в единую форму, которую мы можем использовать для теста:
;; compute public-key-string and private-key-string as before
(let [contents (format "Public Key: %s\nPrivate Key: %s"
public-key-string secret-key-string)]
(spit file-path contents)
Тест может быть примерно таким:
(deftest saving-keypair
(testing "Successful save"
(let [file-mock (atom nil)]
;; During this test we redefine `spit` to save into the atom defined above
(with-redefs [spit (fn [path data] (reset! file-mock {:path path :data data}))]
;; Perform IO action
(save-keypair "~/.ssb-clj/secret" {:public "XXXX" :private "YYYYY"})
;; Test if the expected data was saved in the file-mock
(is (= {:path "~/.ssb-clj/secret" :data "Public key: XXXYYYZZZ\nXXXYYYZZ"}
@file-mock))
Используйте взаимодействие Java с File
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/File.html
В частности, см. File.createTempFile()
и либо file.delete()
или file.deleteOnExit()
. Итак, вы создаете временный файл, используете его в своем модульном тесте, читаете только что написанный файл и проверяете его содержимое. Затем либо удалите файл явно (в идеале внутри try / finally) с автоматическим удалением в качестве резервной копии.
В зависимости от того, как вы настроили ожидаемые результаты в своих тестах, вам может быть полезно следующее:
- https://clojuredocs.org/clojure.string/trim
- tupelo.string / collapse-whitespace
- tupelo.string / nonblank =
Эти вспомогательные функции особенно полезны для вывода текстового файла, где наличие завершающего newline
char может зависеть от ОС. Они также помогают игнорировать различия из-за того, что "новая строка" является CR, CR/LF или LF.