add tests
This commit is contained in:
parent
aa58b3116c
commit
0bf94fa60f
12
project.clj
12
project.clj
|
@ -9,7 +9,11 @@
|
|||
[com.github.jsqlparser/jsqlparser "0.9.5"]]
|
||||
|
||||
:profiles {:provided
|
||||
{:dependencies
|
||||
[[org.clojure/clojure "1.8.0"]
|
||||
[org.clojure/java.jdbc "0.6.1"]
|
||||
[gered/views "1.5-SNAPSHOT"]]}})
|
||||
{:dependencies [[org.clojure/clojure "1.8.0"]
|
||||
[org.clojure/java.jdbc "0.6.1"]
|
||||
[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!)]}})
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
(if-not stmt-type
|
||||
(throw (new Exception "Unsupported SQL query. Only SELECT, INSERT, UPDATE and DELETE queries are supported!"))
|
||||
{:type stmt-type
|
||||
:returning? (sql-stmt-returning? stmt stmt-type)
|
||||
:returning? (boolean (sql-stmt-returning? stmt stmt-type))
|
||||
:tables (get-query-tables-set stmt)})))
|
||||
|
||||
(defonce query-info-cache (atom {}))
|
||||
|
|
51
test/views/sql/sql_analysis_tests.clj
Normal file
51
test/views/sql/sql_analysis_tests.clj
Normal 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)))))
|
16
test/views/sql/test_fixtures.clj
Normal file
16
test/views/sql/test_fixtures.clj
Normal 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))
|
78
test/views/sql/vexec_tests.clj
Normal file
78
test/views/sql/vexec_tests.clj
Normal 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)))))
|
96
test/views/sql/view_test.clj
Normal file
96
test/views/sql/view_test.clj
Normal 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))))))
|
Loading…
Reference in a new issue