我找到了一种通过使用s/or
规范生成值来抛出NullPointerExceptions的方法。我希望能够生成和标记nil
值,没有不适合s/nilable
。
这是clojure.spec
中的错误吗?
(ns blah
(:require [clojure.spec.alpha :as s]))
(s/def ::fine (s/or :int int? :nil nil?)
(s/def ::throws (s/or :int (s/int-in 1 5) :zero zero? :nil nil?)
(s/exercise ::fine)
=>
([nil [:nil nil]
[-1 [:int -1]]
[nil [:nil nil]]
[0 [:int 0]]
[nil [:nil nil]]
[15 [:int 15]]
[-25 [:int -25]]
[nil [:nil nil]]
[-2 [:int -2]]
[-30 [:int -30]]])]])
(s/exercise ::throws)
=>
NullPointerException clojure.lang.Numbers.ops (Numbers.java:1018)
如果您限制::throws
的次数,您会看到正确的:int
和:zero
值,这是抛出的:nil
。
这有效:
(s/def ::works (s/or :int (s/int-in 1 5) :nil nil? :zero zero?))
我假设规范将尝试按照or
替代方案的顺序保持一致。使用zero?
谓词符合nil
会崩溃,但将nil?
移到谓词前面,将防止这种情况发生。
同样有效的是使用集合而不是谓词:
(s/def ::throws (s/or :int (s/int-in 1 5) :zero #{0} :nil nil?))