From 7581ecd6c0e4941cf5a97105c8382f051be9ff35 Mon Sep 17 00:00:00 2001 From: robacarp Date: Sun, 22 Apr 2018 11:20:31 -0600 Subject: [PATCH] Spec for from_sql, and a big mock for the DB class (#133) * Spec for from_sql, and a big mock for the DB class * Updates to work with sqlite timestamp hack * cleanup and documentation --- spec/granite_orm/querying/from_sql_spec.cr | 41 ++++++++++ spec/mocks/db_mock.cr | 89 ++++++++++++++++++++++ spec/spec_helper.cr | 1 + spec/spec_models.cr | 3 +- 4 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 spec/granite_orm/querying/from_sql_spec.cr create mode 100644 spec/mocks/db_mock.cr diff --git a/spec/granite_orm/querying/from_sql_spec.cr b/spec/granite_orm/querying/from_sql_spec.cr new file mode 100644 index 00000000..25548dd2 --- /dev/null +++ b/spec/granite_orm/querying/from_sql_spec.cr @@ -0,0 +1,41 @@ +require "../../spec_helper" + +macro build_review_emitter(driver) + {% + timestamp = if driver == "sqlite" + "2018-04-09 13:33:46" + else + "Time.now".id + end + %} + + FieldEmitter.new.tap do |e| + e._set_values( + [ + 8_i64, + "name", + nil, # downvotes + nil, # upvotes + nil, # sentiment + nil, # interest + true, # published + {{ timestamp }} # created_at + ] + ) + end +end + +def method_which_takes_any_model(model : Granite::ORM::Base.class) + model.as(Granite::ORM::Base).from_sql build_review_emitter +end + +{% for adapter in GraniteExample::ADAPTERS %} + module {{ adapter.capitalize.id }} + describe "{{ adapter.id }} #from_sql" do + it "Builds a model from a resultset" do + model = Review.from_sql build_review_emitter({{ adapter }}) + model.class.should eq Review + end + end + end +{% end %} diff --git a/spec/mocks/db_mock.cr b/spec/mocks/db_mock.cr new file mode 100644 index 00000000..30c6921b --- /dev/null +++ b/spec/mocks/db_mock.cr @@ -0,0 +1,89 @@ +class FakeStatement < DB::Statement + protected def perform_query(args : Enumerable) : DB::ResultSet + FieldEmitter.new + end + + protected def perform_exec(args : Enumerable) + DB::ExecResult.new 0_i64, 0_i64 + end +end + +class FakeContext + include DB::ConnectionContext + + def uri + URI.new "" + end + + def prepared_statements? + false + end + + def discard(connection); end + def release(connection); end +end + +class FakeConnection < DB::Connection + def initialize + @context = FakeContext.new + @prepared_statements = false + end + + def build_unprepared_statement(query : String) + FakeStatement.new self + end + + def build_prepared_statement(query : String) + FakeStatement.new self + end +end + +# FieldEmitter emulates the subtle and uninformed way that +# DB::ResultSet emits data. To be used in testing interactions +# with raw data sets. +class FieldEmitter < DB::ResultSet + # 1. Override `#move_next` to move to the next row. + # 2. Override `#read` returning the next value in the row. + # 3. (Optional) Override `#read(t)` for some types `t` for which custom logic other than a simple cast is needed. + # 4. Override `#column_count`, `#column_name`. + + @position = 0 + @field_position = 0 + @values = [] of DB::Any + + def initialize + @statement = FakeStatement.new FakeConnection.new + end + + def _set_values(values : Array(DB::Any)) + @values = [] of DB::Any + values.each do |v| + @values << v + end + end + + def move_next + @position += 1 + @field_position = 0 + end + + def read + if @position >= @values.size + raise "Overread" + end + + + @values[@position].tap do |v| + @position += 1 + end + end + + def column_count + @values.size + end + + def column_name(index : Int32) + "Column #{index}" + end +end + diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr index 988181e7..5fd40842 100644 --- a/spec/spec_helper.cr +++ b/spec/spec_helper.cr @@ -6,5 +6,6 @@ end require "../src/granite_orm" require "./spec_models" +require "./mocks/**" Granite::ORM.settings.logger = ::Logger.new(nil) diff --git a/spec/spec_models.cr b/spec/spec_models.cr index 2928bb68..01de3cf9 100644 --- a/spec/spec_models.cr +++ b/spec/spec_models.cr @@ -204,8 +204,7 @@ end sentiment FLOAT, interest REAL, published BOOL, - {{ created_at_sql }}, - {{ updated_at_sql }} + {{ created_at_sql }} ) SQL end