add tests

This commit is contained in:
Gered 2016-05-31 18:20:09 -04:00
parent aa58b3116c
commit 0bf94fa60f
6 changed files with 250 additions and 5 deletions

View file

@ -9,7 +9,11 @@
[com.github.jsqlparser/jsqlparser "0.9.5"]] [com.github.jsqlparser/jsqlparser "0.9.5"]]
:profiles {:provided :profiles {:provided
{:dependencies {:dependencies [[org.clojure/clojure "1.8.0"]
[[org.clojure/clojure "1.8.0"] [org.clojure/java.jdbc "0.6.1"]
[org.clojure/java.jdbc "0.6.1"] [gered/views "1.5-SNAPSHOT"]]}
[gered/views "1.5-SNAPSHOT"]]}})
:test
{:dependencies [[pjstadig/humane-test-output "0.8.0"]]
:injections [(require 'pjstadig.humane-test-output)
(pjstadig.humane-test-output/activate!)]}})

View file

@ -48,7 +48,7 @@
(if-not stmt-type (if-not stmt-type
(throw (new Exception "Unsupported SQL query. Only SELECT, INSERT, UPDATE and DELETE queries are supported!")) (throw (new Exception "Unsupported SQL query. Only SELECT, INSERT, UPDATE and DELETE queries are supported!"))
{:type stmt-type {:type stmt-type
:returning? (sql-stmt-returning? stmt stmt-type) :returning? (boolean (sql-stmt-returning? stmt stmt-type))
:tables (get-query-tables-set stmt)}))) :tables (get-query-tables-set stmt)})))
(defonce query-info-cache (atom {})) (defonce query-info-cache (atom {}))

View file

@ -0,0 +1,51 @@
(ns views.sql.sql-analysis-tests
(:use
clojure.test
views.sql.test-fixtures
views.sql.core))
(use-fixtures :each clear-query-cache-fixture)
;; NOTE: the purpose of the tests which look at analysis results of SQL queries
;; is __NOT__ to test how good the support of JSqlParser is, but just
;; to ensure that the views.sql abstraction over it works.
(deftest select-query-analyzed-correctly
(let [info (query-info "SELECT * FROM book WHERE price > 100.00 ORDER BY title")]
(is (= :select (:type info)))
(is (= true (:returning? info)))
(is (= #{:book} (:tables info)))))
(deftest insert-query-analyzed-correctly
(let [info (query-info "INSERT INTO example (field1, field2, field3) VALUES ('test', 'N', NULL)")]
(is (= :insert (:type info)))
(is (= false (:returning? info)))
(is (= #{:example} (:tables info)))))
(deftest insert-query-with-returning-clause-analyzed-correctly
(let [info (query-info "INSERT INTO example (field1, field2, field3) VALUES ('test', 'N', NULL) RETURNING *")]
(is (= :insert (:type info)))
(is (= true (:returning? info)))
(is (= #{:example} (:tables info)))))
(deftest update-query-analyzed-correctly
(let [info (query-info "UPDATE example SET field1 = 'updated value' WHERE field2 = 'N'")]
(is (= :update (:type info)))
(is (= false (:returning? info)))
(is (= #{:example} (:tables info)))))
(deftest delete-query-analyzed-correctly
(let [info (query-info "DELETE FROM example WHERE field2 = 'N'")]
(is (= :delete (:type info)))
(is (= false (:returning? info)))
(is (= #{:example} (:tables info)))))
(deftest unsupported-query-types-throw-exception
(is (thrown? Exception (query-info "ALTER TABLE example ADD column4 NUMBER(3) NOT NULL"))))
(deftest multiple-query-tables-are-included-correctly
(let [info (query-info "SELECT * FROM book JOIN publisher ON book.publisher_id = publisher.id WHERE price > 100.00 ORDER BY title")]
(is (= :select (:type info)))
(is (= true (:returning? info)))
(is (= #{:book :publisher} (:tables info)))))

View file

@ -0,0 +1,16 @@
(ns views.sql.test-fixtures
(:use
clojure.test
views.sql.core))
(def test-db {:not-a-real-db-conn true})
(def test-view-system (atom {}))
(defn clear-query-cache-fixture [f]
(reset! query-info-cache {})
(f))
(defn reset-test-view-system-fixture [f]
(reset! test-view-system {})
(f))

View file

@ -0,0 +1,78 @@
(ns views.sql.vexec-tests
(:use
clojure.test
views.sql.test-fixtures
views.sql.core)
(:require
[clojure.java.jdbc :as jdbc]
[views.core :as views]))
(def redefs-called (atom {}))
(defn ->redef-fn
[name & [return-value]]
(fn [& args]
(swap! redefs-called assoc name (vec args))
return-value))
(defn vexec-redefs-fixture [f]
(reset! redefs-called {})
(with-redefs
[jdbc/query (->redef-fn :jdbc/query :jdbc/query-return-value)
jdbc/execute! (->redef-fn :jdbc/execute! :jdbc/execute!-return-value)
views/put-hints! (->redef-fn :views/put-hints!)]
(f)))
(use-fixtures :each clear-query-cache-fixture reset-test-view-system-fixture vexec-redefs-fixture)
(deftest vexec-runs-query-and-puts-hints
(let [sqlvec ["INSERT INTO example (field1, field2, field3) VALUES ('test', 'N', NULL)"]
result (vexec! test-view-system test-db sqlvec)]
(is (= [test-db sqlvec] (:jdbc/execute! @redefs-called)))
(is (= :jdbc/execute!-return-value result))
(is (= [test-view-system [(views/hint nil #{:example} hint-type)]]
(:views/put-hints! @redefs-called)))))
(deftest vexec-runs-query-with-returning-clause
(let [sqlvec ["INSERT INTO example (field1, field2, field3) VALUES ('test', 'N', NULL) RETURNING *"]
result (vexec! test-view-system test-db sqlvec)]
(is (= [test-db sqlvec] (:jdbc/query @redefs-called)))
(is (= :jdbc/query-return-value result))
(is (= [test-view-system [(views/hint nil #{:example} hint-type)]]
(:views/put-hints! @redefs-called)))))
(deftest namespace-is-passed-along-to-hints-via-vexec
(let [sqlvec ["INSERT INTO example (field1, field2, field3) VALUES ('test', 'N', NULL)"]
result (vexec! test-view-system test-db sqlvec {:namespace :foobar})]
(is (= [test-db sqlvec] (:jdbc/execute! @redefs-called)))
(is (= :jdbc/execute!-return-value result))
(is (= [test-view-system [(views/hint :foobar #{:example} hint-type)]]
(:views/put-hints! @redefs-called)))))
(deftest manually-provided-hints-to-vexec-are-passed-to-views-system
(let [sqlvec ["INSERT INTO example (field1, field2, field3) VALUES ('test', 'N', NULL)"]
result (vexec! test-view-system test-db sqlvec [:foo :bar])]
(is (= [test-db sqlvec] (:jdbc/execute! @redefs-called)))
(is (= :jdbc/execute!-return-value result))
(is (= [test-view-system [(views/hint nil #{:foo :bar} hint-type)]]
(:views/put-hints! @redefs-called)))))
(deftest manually-provided-hints-to-vexec-also-requires-specifying-returning-option
(let [sqlvec ["INSERT INTO example (field1, field2, field3) VALUES ('test', 'N', NULL) RETURNING *"]
result (vexec! test-view-system test-db sqlvec [:foo :bar])]
; means jdbc/execute! was called which is correct behaviour since the returning option was not specified.
; if jdbc/execute! was really called it would throw an exception since the INSERT query used has a RETURNING clause
(is (= [test-db sqlvec] (:jdbc/execute! @redefs-called)))
(is (= :jdbc/execute!-return-value result))
(is (= [test-view-system [(views/hint nil #{:foo :bar} hint-type)]]
(:views/put-hints! @redefs-called))))
; manually reset some things
(reset! redefs-called {})
(reset! query-info-cache {})
(let [sqlvec ["INSERT INTO example (field1, field2, field3) VALUES ('test', 'N', NULL) RETURNING *"]
result (vexec! test-view-system test-db sqlvec [:foo :bar] {:returning? true})]
(is (= [test-db sqlvec] (:jdbc/query @redefs-called)))
(is (= :jdbc/query-return-value result))
(is (= [test-view-system [(views/hint nil #{:foo :bar} hint-type)]]
(:views/put-hints! @redefs-called)))))

View file

@ -0,0 +1,96 @@
(ns views.sql.view-test
(:import (views.protocols IView))
(:use
clojure.test
views.sql.test-fixtures
views.sql.core
views.sql.view
views.protocols)
(:require
[clojure.java.jdbc :as jdbc]
[views.core :as views]))
(def redefs-called (atom {}))
(defn ->redef-fn
[name & [return-value]]
(fn [& args]
(swap! redefs-called assoc name (vec args))
return-value))
(defn vexec-redefs-fixture [f]
(reset! redefs-called {})
(with-redefs
[jdbc/query (->redef-fn :jdbc/query :jdbc/query-return-value)
views/put-hints! (->redef-fn :views/put-hints!)]
(f)))
(use-fixtures :each clear-query-cache-fixture reset-test-view-system-fixture vexec-redefs-fixture)
(deftest basic-sql-view-works
(let [sqlvec ["SELECT * FROM foobar"]
sql-fn (fn [] sqlvec)
sql-view (view :test-view test-db sql-fn)]
(is (satisfies? IView sql-view))
(is (= :test-view (id sql-view)))
(is (= true (relevant? sql-view nil [] [(views/hint nil #{:foobar} hint-type)])))
(is (= false (relevant? sql-view nil [] [(views/hint nil #{:baz} hint-type)])))
(is (= :jdbc/query-return-value (data sql-view nil [])))
(is (= [test-db sqlvec {}]
(:jdbc/query @redefs-called)))))
(deftest basic-sql-view-works-with-parameters
(let [sqlvec ["SELECT * FROM foobar"]
sql-fn (fn [a b] (into sqlvec [a b]))
sql-view (view :test-view test-db sql-fn)]
(is (= true (relevant? sql-view nil [1 2] [(views/hint nil #{:foobar} hint-type)])))
(is (= :jdbc/query-return-value (data sql-view nil [1 2])))
(is (= [test-db (into sqlvec [1 2]) {}]
(:jdbc/query @redefs-called)))))
(deftest basic-sql-view-works-with-namespace
(let [sqlvec ["SELECT * FROM foobar"]
sql-fn (fn [] sqlvec)
sql-view (view :test-view test-db sql-fn)]
(is (= true (relevant? sql-view :abc [] [(views/hint :abc #{:foobar} hint-type)])))
(is (= false (relevant? sql-view :123 [] [(views/hint :abc #{:foobar} hint-type)])))
(is (= :jdbc/query-return-value (data sql-view nil [])))
(is (= [test-db sqlvec {}]
(:jdbc/query @redefs-called)))))
(deftest view-db-fn-is-used-when-provided
(let [alt-test-db {:alternate-test-db-conn true}
db-fn (fn [namespace] alt-test-db)
sqlvec ["SELECT * FROM foobar"]
sql-fn (fn [] sqlvec)
sql-view (view :test-view db-fn sql-fn)]
(is (= :jdbc/query-return-value (data sql-view nil [])))
(is (= [alt-test-db sqlvec {}]
(:jdbc/query @redefs-called)))))
(deftest view-db-fn-is-passed-namespace
(let [test-namespace :test-namespace
alt-test-db {:alternate-test-db-conn true}
db-fn (fn [namespace]
(is (= namespace :test-namespace))
alt-test-db)
sqlvec ["SELECT * FROM foobar"]
sql-fn (fn [] sqlvec)
sql-view (view :test-view db-fn sql-fn)]
(is (= :jdbc/query-return-value (data sql-view test-namespace [])))
(is (= [alt-test-db sqlvec {}]
(:jdbc/query @redefs-called)))))
(deftest manually-specified-view-hints-are-used-correctly
(with-redefs
[query-tables (->redef-fn :query-tables)]
(let [sqlvec ["SELECT * FROM foobar"]
sql-fn (fn [] sqlvec)
sql-view (view :test-view test-db sql-fn [:foo :bar])]
(is (= false (relevant? sql-view nil [] [(views/hint nil #{:foobar} hint-type)])))
(is (= true (relevant? sql-view nil [] [(views/hint nil #{:foo} hint-type)])))
(is (= true (relevant? sql-view nil [] [(views/hint nil #{:bar} hint-type)])))
(is (= true (relevant? sql-view nil [] [(views/hint nil #{:bar} hint-type)
(views/hint nil #{:foo} hint-type)])))
(is (not (contains? @redefs-called :query-tables))))))