Meaningful error message for Clojure.Spec validation in :pre

后端 未结 4 1828
耶瑟儿~
耶瑟儿~ 2021-02-05 06:42

I used the last days to dig deeper into clojure.spec in Clojure and ClojureScript.

Until now I find it most useful, to use specs as guards in :pre

4条回答
  •  隐瞒了意图╮
    2021-02-05 07:29

    Without taking into account if you should use pre and post conditions to validate function arguments, there is a way to print somewhat clearer messages from pre and post conditions by wrapping your predicate with clojure.test/is, as suggested in the answer below:

    How can I get Clojure :pre & :post to report their failing value?

    So then your code could look like this:

    (ns pre-post-messages.core
      (:require [clojure.spec :as s]
                [clojure.test :as t]))
    
    (defn person-name [person]
      {:pre [(t/is (s/valid? ::person person))]
       :post [(t/is (s/valid? string? %))]}
      (str (::first-name person) " " (::last-name person)))
    
    (def try-1
      {:first-name "Anna Vissi"})
    
    (def try-2
      {::first-name "Anna"
       ::last-name "Vissi"
       ::email "Anna@Vissi.com"})
    
    (s/def ::person (s/keys :req [::first-name ::last-name ::email]))
    

    Evaluating

    pre-post-messages.core> (person-name  try-2)
    

    would produce

    "Anna Vissi"
    

    and evaluating

    pre-post-messages.core> (person-name  try-1)
    

    would produce

    FAIL in () (core.clj:6)
    
    expected: (s/valid? :pre-post-messages.core/person person)
    
      actual: (not (s/valid? :pre-post-messages.core/person {:first-name "Anna Vissi"}))
    
    AssertionError Assert failed: (t/is (s/valid? :pre-post-messages.core/person person))  pre-post-messages.core/person-name (core.clj:5)
    

提交回复
热议问题