active_mocker 1.2.4 → 1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -11
- data/active_mocker.gemspec +1 -1
- data/lib/active_hash/ar_api.rb +23 -4
- data/lib/active_hash/init.rb +5 -1
- data/lib/active_mocker.rb +0 -1
- data/lib/active_mocker/collection/association.rb +12 -0
- data/lib/active_mocker/collection/base.rb +65 -0
- data/lib/active_mocker/collection/queries.rb +105 -0
- data/lib/active_mocker/collection/relation.rb +11 -0
- data/lib/active_mocker/mock_instance_methods.rb +3 -1
- data/lib/active_mocker/mock_requires.rb +3 -1
- data/lib/active_mocker/mock_template.erb +6 -6
- data/lib/active_mocker/version.rb +1 -1
- data/sample_app_rails_4/config/application.rb +1 -1
- data/sample_app_rails_4/db/schema.rb +1 -0
- data/sample_app_rails_4/spec/compare_mocker_and_record_spec.rb +496 -42
- data/sample_app_rails_4/spec/mocks/micropost_mock.rb +19 -10
- data/sample_app_rails_4/spec/mocks/relationship_mock.rb +8 -8
- data/sample_app_rails_4/spec/mocks/user_mock.rb +22 -22
- data/sample_app_rails_4/spec/user_mock_spec.rb +0 -1
- data/spec/lib/active_mocker/{collection_association_spec.rb → collection.rb} +4 -5
- data/spec/lib/active_mocker/generate_spec.rb +19 -30
- metadata +12 -11
- data/lib/active_hash/find_by.rb +0 -31
- data/lib/active_hash/update.rb +0 -18
- data/lib/active_mocker/collection_association.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 469e40ce463c581d08ddf136c0a2e91082680baf
|
4
|
+
data.tar.gz: 347c0a56642bddfe071b63022705ada95e85baf9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8c4e249f4eb55352ce3f3815a3f0daef791109970bdbf6e3fd89f035afe95967a583d4133c7b70fe20b98bac0aadca964f5bc512b99aa932ff335dc1ebfc90c
|
7
|
+
data.tar.gz: c672f2b89c749780ac4797357d2fd15e01a0d816fcd36f41c9246f3bf5c4b76be3cc721ab024c7f5dca81d89ab1fca15d2736b301c8beb65b6208875d7f491e8
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# ActiveMocker
|
2
2
|
[![Build Status](https://travis-ci.org/zeisler/active_mocker.png?branch=master)](https://travis-ci.org/zeisler/active_mocker)
|
3
3
|
|
4
|
-
Creates mocks from Active Record models. Allows your test suite to run very fast by not loading Rails or hooking to a database. It parse the schema definition and the
|
4
|
+
Creates mocks from Active Record models. Allows your test suite to run very fast by not loading Rails or hooking to a database. It parse the schema definition and the defined methods on a model then saves a ruby file that can be included with a test. Mocks are regenerated when the schema is modified so your mocks will not go stale. This prevents the case where your units tests pass but production code is failing.
|
5
5
|
|
6
6
|
Example from a real app
|
7
7
|
|
@@ -166,27 +166,28 @@ Here is an example of a rake task to regenerate mocks after every schema modifia
|
|
166
166
|
### ActiveRecord supported methods
|
167
167
|
**class methods**
|
168
168
|
|
169
|
-
* new
|
170
|
-
* create
|
169
|
+
* new
|
170
|
+
* create/create!
|
171
171
|
* column_names
|
172
172
|
* find
|
173
|
-
* find_by
|
174
|
-
* find_by!
|
173
|
+
* find_by/find_by!
|
175
174
|
* find_or_create_by
|
176
175
|
* find_or_initialize_by
|
177
|
-
* where
|
176
|
+
* where(conditions_hash)
|
178
177
|
* delete_all/destroy_all
|
178
|
+
* delete_all(conditions_hash)
|
179
|
+
* destroy(id)/delete(id)
|
179
180
|
* all
|
180
181
|
* count
|
181
182
|
* first/last
|
183
|
+
|
182
184
|
|
183
185
|
**instance methods**
|
184
186
|
|
185
|
-
* attributes
|
187
|
+
* attributes
|
186
188
|
* update
|
187
|
-
* save
|
188
|
-
* write_attribute - (private, can be used within an included module)
|
189
|
-
* read_attribute - (private)
|
189
|
+
* save/save!
|
190
|
+
* write_attribute/read_attribute - (private, can be used within an included module)
|
190
191
|
|
191
192
|
**has_many associations**
|
192
193
|
|
@@ -210,7 +211,6 @@ Here is an example of a rake task to regenerate mocks after every schema modifia
|
|
210
211
|
|
211
212
|
* Model names and table names must follow the default ActiveRecord naming pattern.
|
212
213
|
* Included/extended module methods will not be included on the mock. I suggest you keep domain logic out of the model and only add database queries. Domain logic can be put into modules and then included into the mock during test setup.
|
213
|
-
* Deleting one record at a time is not support, this is a limitation of ActiveHash.
|
214
214
|
* Queries will not call other mocks classes, for example when using `where` all attributes must reside inside of each record.
|
215
215
|
|
216
216
|
## Inspiration
|
data/active_mocker.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Dustin Zeisler"]
|
10
10
|
spec.email = ["dustin@zive.me"]
|
11
11
|
spec.summary = %q{Creates mocks from Active Record models. Allows your test suite to run very fast by not loading Rails or hooking to a database.}
|
12
|
-
spec.description = %q{Creates mocks from Active Record models. Allows your test suite to run very fast by not loading Rails or hooking to a database. It parse the schema definition and the
|
12
|
+
spec.description = %q{Creates mocks from Active Record models. Allows your test suite to run very fast by not loading Rails or hooking to a database. It parse the schema definition and the defined methods on a model then saves a ruby file that can be included with a test. Mocks are regenerated when the schema is modified so your mocks will not go stale. This prevents the case where your units tests pass but production code is failing.}
|
13
13
|
spec.homepage = "https://github.com/zeisler/active_mocker"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
data/lib/active_hash/ar_api.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
require_relative 'update'
|
2
|
-
require_relative 'find_by'
|
3
1
|
require_relative 'init'
|
2
|
+
require_relative '../active_mocker/collection/queries'
|
3
|
+
require_relative '../active_mocker/collection/base'
|
4
|
+
require_relative '../active_mocker/collection/relation'
|
4
5
|
module ActiveMocker
|
5
6
|
module ActiveHash
|
6
7
|
|
7
8
|
module ARApi
|
8
9
|
|
9
|
-
include ::ActiveHash::ARApi::Update
|
10
10
|
include ::ActiveHash::ARApi::Init
|
11
11
|
|
12
12
|
def delete
|
@@ -16,12 +16,27 @@ module ActiveMocker
|
|
16
16
|
records.delete_at(index)
|
17
17
|
end
|
18
18
|
|
19
|
+
def update(options={})
|
20
|
+
options.each do |method, value|
|
21
|
+
send("#{method}=", value)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
19
26
|
def self.included(base)
|
20
27
|
base.extend(ClassMethods)
|
21
28
|
end
|
22
29
|
|
23
30
|
module ClassMethods
|
24
|
-
include ::
|
31
|
+
include ActiveMocker::Collection::Queries
|
32
|
+
|
33
|
+
def create(attributes = {}, &block)
|
34
|
+
record = new(attributes)
|
35
|
+
record = new(attributes, &block) if block_given?
|
36
|
+
record.save
|
37
|
+
mark_dirty
|
38
|
+
record
|
39
|
+
end
|
25
40
|
|
26
41
|
def find_or_create_by(attributes)
|
27
42
|
find_by(attributes) || create(attributes)
|
@@ -35,6 +50,10 @@ module ActiveMocker
|
|
35
50
|
find(id).delete
|
36
51
|
end
|
37
52
|
|
53
|
+
def to_a
|
54
|
+
@records
|
55
|
+
end
|
56
|
+
|
38
57
|
alias_method :destroy, :delete
|
39
58
|
|
40
59
|
def delete_all(options=nil)
|
data/lib/active_hash/init.rb
CHANGED
@@ -6,8 +6,9 @@ module ActiveHash
|
|
6
6
|
|
7
7
|
attr_reader :associations, :types
|
8
8
|
|
9
|
-
def initialize(attributes = {})
|
9
|
+
def initialize(attributes = {}, &block)
|
10
10
|
@types = {}
|
11
|
+
yield self if block_given?
|
11
12
|
attributes.each do |key, value|
|
12
13
|
begin
|
13
14
|
send "#{key}=", value
|
@@ -17,6 +18,9 @@ module ActiveHash
|
|
17
18
|
end
|
18
19
|
|
19
20
|
end
|
21
|
+
|
22
|
+
|
23
|
+
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
data/lib/active_mocker.rb
CHANGED
@@ -16,7 +16,6 @@ require 'active_mocker/active_record'
|
|
16
16
|
require 'active_mocker/model_reader'
|
17
17
|
require 'active_mocker/schema_reader'
|
18
18
|
require 'active_mocker/active_record/schema'
|
19
|
-
require 'active_mocker/collection_association'
|
20
19
|
require 'active_mocker/active_record'
|
21
20
|
require 'active_mocker/model_reader'
|
22
21
|
require 'active_mocker/reparameterize'
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module ActiveMocker
|
2
|
+
|
3
|
+
module Collection
|
4
|
+
|
5
|
+
|
6
|
+
class Base
|
7
|
+
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
def initialize(collection=[])
|
11
|
+
@collection = [*collection]
|
12
|
+
end
|
13
|
+
|
14
|
+
def <<(*records)
|
15
|
+
collection.concat(records.flatten)
|
16
|
+
end
|
17
|
+
|
18
|
+
delegate :take, :push, :clear, :first, :last, :concat, :replace, :distinct, :uniq, :count, :size, :length, :empty?, :any?, :include?, :delete, to: :collection
|
19
|
+
alias distinct uniq
|
20
|
+
|
21
|
+
# def delete(obj)
|
22
|
+
# collection.delete(obj)
|
23
|
+
# end
|
24
|
+
|
25
|
+
def order(key)
|
26
|
+
self.class.new(collection.sort_by{ |item| item.send(key) })
|
27
|
+
end
|
28
|
+
|
29
|
+
def reverse_order
|
30
|
+
self.class.new(collection.reverse)
|
31
|
+
end
|
32
|
+
|
33
|
+
def select(&block)
|
34
|
+
self.class.new(collection.select(&block))
|
35
|
+
end
|
36
|
+
|
37
|
+
def each(&block)
|
38
|
+
self.class.new(collection.each do |item|
|
39
|
+
block.call(item)
|
40
|
+
end)
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_a
|
44
|
+
@collection
|
45
|
+
end
|
46
|
+
|
47
|
+
def ==(val)
|
48
|
+
return false if val.nil?
|
49
|
+
collection.hash == val.hash
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def collection
|
55
|
+
@collection
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module ActiveMocker
|
2
|
+
|
3
|
+
class RecordNotFound < Exception
|
4
|
+
|
5
|
+
end
|
6
|
+
module Collection
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
module Queries
|
11
|
+
|
12
|
+
def delete_all
|
13
|
+
all.map(&:delete)
|
14
|
+
end
|
15
|
+
|
16
|
+
def destroy_all
|
17
|
+
delete_all
|
18
|
+
end
|
19
|
+
|
20
|
+
def all(options={})
|
21
|
+
if options.has_key?(:conditions)
|
22
|
+
where(options[:conditions])
|
23
|
+
else
|
24
|
+
Relation.new( to_a || [] )
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class WhereNotChain
|
29
|
+
|
30
|
+
def initialize(collection)
|
31
|
+
@collection = collection
|
32
|
+
end
|
33
|
+
|
34
|
+
def not(options={})
|
35
|
+
@collection.reject do |record|
|
36
|
+
options.all? { |col, match| record.send(col) == match }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
def where(options=nil)
|
43
|
+
return WhereNotChain.new(all) if options.nil?
|
44
|
+
all.select do |record|
|
45
|
+
options.all? { |col, match| record.send(col) == match }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def find(ids)
|
50
|
+
ids_array = [*ids]
|
51
|
+
results = ids_array.map do |id|
|
52
|
+
where(id: id).first
|
53
|
+
end
|
54
|
+
return Relation.new(results) if ids.class == Array
|
55
|
+
return results.first
|
56
|
+
end
|
57
|
+
|
58
|
+
def update_all(options)
|
59
|
+
all.each{ |i| i.update(options)}
|
60
|
+
end
|
61
|
+
|
62
|
+
def find_by(options = {})
|
63
|
+
send(:where, options).first
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_by!(options={})
|
67
|
+
result = find_by(options)
|
68
|
+
raise RecordNotFound if result.blank?
|
69
|
+
result
|
70
|
+
end
|
71
|
+
|
72
|
+
def limit(num)
|
73
|
+
Relation.new(all.take(num))
|
74
|
+
end
|
75
|
+
|
76
|
+
def sum(key)
|
77
|
+
values = values_by_key(key)
|
78
|
+
values.inject { |sum, n| sum + n }
|
79
|
+
end
|
80
|
+
|
81
|
+
def average(key)
|
82
|
+
values = values_by_key(key)
|
83
|
+
total = values.inject { |sum, n| sum + n }
|
84
|
+
BigDecimal.new(total) / BigDecimal.new(values.count)
|
85
|
+
end
|
86
|
+
|
87
|
+
def minimum(key)
|
88
|
+
values_by_key(key).min_by{|i| i }
|
89
|
+
end
|
90
|
+
|
91
|
+
def maximum(key)
|
92
|
+
values_by_key(key).max_by { |i| i }
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def values_by_key(key)
|
98
|
+
all.map { |obj| obj.send(key) }
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
@@ -1,4 +1,6 @@
|
|
1
|
-
require 'active_mocker/
|
1
|
+
require 'active_mocker/collection/queries'
|
2
|
+
require 'active_mocker/collection/base'
|
3
|
+
require 'active_mocker/collection/association'
|
2
4
|
require 'active_mocker/mock_class_methods'
|
3
5
|
require 'active_mocker/mock_instance_methods'
|
4
6
|
require 'active_hash'
|
@@ -6,10 +6,10 @@ class <%= class_name %> < ::ActiveHash::Base
|
|
6
6
|
include ActiveMocker::MockInstanceMethods
|
7
7
|
extend ActiveMocker::MockClassMethods
|
8
8
|
|
9
|
-
def initialize(attributes
|
9
|
+
def initialize(attributes={}, &block)
|
10
10
|
@attributes = HashWithIndifferentAccess.new(<%= default_attributes %>)
|
11
11
|
@associations = HashWithIndifferentAccess.new(<%= associations %>)
|
12
|
-
super(attributes)
|
12
|
+
super(attributes, &block)
|
13
13
|
end
|
14
14
|
|
15
15
|
|
@@ -18,7 +18,7 @@ class <%= class_name %> < ::ActiveHash::Base
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.attribute_names
|
21
|
-
@attribute_names = <%= attribute_names
|
21
|
+
@attribute_names = <%= attribute_names %>
|
22
22
|
end
|
23
23
|
|
24
24
|
##################################
|
@@ -26,7 +26,7 @@ class <%= class_name %> < ::ActiveHash::Base
|
|
26
26
|
##################################
|
27
27
|
<% attributes.each do |meth| %>
|
28
28
|
def <%= meth.name %>
|
29
|
-
|
29
|
+
@attributes['<%= meth.name %>']
|
30
30
|
end
|
31
31
|
|
32
32
|
def <%= meth.name %>=(val)
|
@@ -52,11 +52,11 @@ class <%= class_name %> < ::ActiveHash::Base
|
|
52
52
|
<% end -%>
|
53
53
|
<% collection_associations.each do |meth| %>
|
54
54
|
def <%= meth %>
|
55
|
-
associations['<%= meth %>'] ||= ActiveMocker::
|
55
|
+
associations['<%= meth %>'] ||= ActiveMocker::Collection::Association.new
|
56
56
|
end
|
57
57
|
|
58
58
|
def <%= meth %>=(val)
|
59
|
-
associations['<%= meth %>'] = ActiveMocker::
|
59
|
+
associations['<%= meth %>'] = ActiveMocker::Collection::Association.new(val)
|
60
60
|
end
|
61
61
|
<% end -%>
|
62
62
|
|
@@ -5,7 +5,7 @@
|
|
5
5
|
# require "rails/test_unit/railtie"
|
6
6
|
|
7
7
|
# Assets should be precompiled for production (so we don't need the gems loaded then)
|
8
|
-
Bundler.require(*Rails.groups(assets: %w(development test)))
|
8
|
+
# Bundler.require(*Rails.groups(assets: %w(development test)))
|
9
9
|
|
10
10
|
module SampleApp
|
11
11
|
class Application < Rails::Application
|