rspec-armour 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3cd64c8d03babf2b9a79453d2c6c2eaa62126ad2880135e73c03fe6d6f56e824
4
- data.tar.gz: 91a57cfa13c6a701acc53ee7281a9cf64608c4dd4fe87f96d0290d0a575bf8ca
3
+ metadata.gz: 6955792ba5e37a3a31d2882b6cf7272ceac0fe1395e539a7a8c25a18d8d17fdf
4
+ data.tar.gz: 1abaa686028e4f96c3d708fe6be34e5c910cbf14b9395fd6ee3692bae32a065d
5
5
  SHA512:
6
- metadata.gz: c29cbe69ed17b4e69bfbbf62e3e79545e789c04ee8f8ba827cce9bcb91334bcaae3732a86716d37ad8e89de00aa355a6089b1e805a8415b03d0c34ff34742d88
7
- data.tar.gz: 21cf05dc106bf0f06ea4ae60f3625f5a6e61c210e037ba0654670e6f89e3a20c471b159e43e5470e9b4820dadea48e3eff8a86cc5fa4086b92c22776ac89c137
6
+ metadata.gz: '03864b7bb2f0486f1c20b3d7ee065dd5262f0ab5fe871d879533d96129fb8a49a4d60860a902f508a3553b53d6b9891e07f1a1c6f0b3264503cf8e4e66a882e9'
7
+ data.tar.gz: b9c7faa924eb1fa56fa1b21fcd672adf19c506118c2d7d4ab89516d2733af4b9d945b1be1519fda3cf1fdcecbea0868c1f596ca297f9175a23e855526f030748
data/CHANGELOG.md CHANGED
@@ -1,4 +1,6 @@
1
- ## [Unreleased]
1
+ ## [0.2.0] - 2026-07-31
2
+
3
+ - Add expect_receive_and_call_original [#1](https://github.com/hlascelles/rspec-armour/pull/1)
2
4
 
3
5
  ## [0.1.0] - 2026-06-04
4
6
 
data/README.md CHANGED
@@ -1,16 +1,20 @@
1
1
  # rspec-armour
2
2
 
3
- `rspec-armour` protects your ActiveRecord models from being mocked or stubbed in RSpec tests. It forces you to use real database objects (or factories) for your models, leading to more robust and reliable tests.
3
+ `rspec-armour` is the RSpec ActiveRecord MockUp Restrictor. It protects your ActiveRecord models
4
+ from being mocked or stubbed in RSpec tests. It forces you to use real database objects (or
5
+ factories) for your models, leading to more robust and reliable tests.
4
6
 
5
7
  ## Installation
6
8
 
7
- Add this line to your application's Gemfile:
9
+ Add `rspec-armour` to the **test group** in your application's `Gemfile`:
8
10
 
9
11
  ```ruby
10
- gem 'rspec-armour'
12
+ group :test do
13
+ gem 'rspec-armour'
14
+ end
11
15
  ```
12
16
 
13
- And then execute:
17
+ Then run:
14
18
 
15
19
  $ bundle install
16
20
 
@@ -22,11 +26,29 @@ Or install it yourself as:
22
26
 
23
27
  Once required, `rspec-armour` automatically prevents mocking of ActiveRecord finders, associations, and persistence methods.
24
28
 
25
- ### Examples of restricted methods:
29
+ ### Examples of restricted methods
30
+
31
+ | Category | Methods |
32
+ |--------------------------|----------------------------------------------------------------------------------------------------------------|
33
+ | **Class finders** | `.find`, `.find_by`, `.find_by!`, `.where`, `.all`, `.first`, `.last`, `.count`, `.pluck`, `.pick`, `.exists?` |
34
+ | **Class persistence** | `.create`, `.create!`, `.update`, `.update!`, `.destroy_all`, `.delete_all`, `.delete_by`, `.destroy_by` |
35
+ | **Instance persistence** | `#save`, `#save!`, `#update`, `#update!`, `#destroy`, `#destroy!`, `#delete`, `#touch`, `#reload` |
36
+ | **Associations** | `has_many`/`belongs_to` reader, writer, and `_ids` helpers (e.g. `user.posts`, `user.posts=`, `user.post_ids`) |
26
37
 
27
- * **Class methods:** `.find`, `.where`, `.create`, `.update`, etc.
28
- * **Instance methods:** `#save`, `#update`, `#destroy`, `#reload`, etc.
29
- * **Associations:** `has_many`, `belongs_to`, and their helper methods (e.g., `user.items`, `user.item_ids`).
38
+ ### What it looks like in practice
39
+
40
+ ```ruby
41
+ # BAD — rspec-armour raises RSpec::Armour::MockError for these:
42
+ allow(User).to receive(:find).and_return(user) # class finder
43
+ allow(User).to receive(:where).and_return([user]) # class finder
44
+ allow(user).to receive(:save).and_return(true) # instance persistence
45
+ allow(user).to receive(:posts).and_return([post]) # association reader
46
+
47
+ # GOOD — use real database objects instead:
48
+ user = create(:user) # FactoryBot / fixtures
49
+ post = create(:post, user:) # real association in the DB
50
+ result = User.where(active: true) # real query against test DB
51
+ ```
30
52
 
31
53
  ### Disabling restrictions
32
54
 
@@ -38,12 +60,18 @@ RSpec::Armour.without_restrictions do
38
60
  end
39
61
  ```
40
62
 
41
- Or by using RSpec metadata:
63
+ Or by using RSpec metadata on an individual example or context:
42
64
 
43
65
  ```ruby
44
66
  it "does something specific", :without_rspec_armour do
45
67
  allow(User).to receive(:where).and_return([])
46
68
  end
69
+
70
+ context "legacy adapter", :without_rspec_armour do
71
+ it "stubs the finder" do
72
+ allow(User).to receive(:find).and_return(double)
73
+ end
74
+ end
47
75
  ```
48
76
 
49
77
  ## Contributing
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Armour
5
+ class ExpectationProxy
6
+ def initialize(expectation, target)
7
+ @expectation = expectation
8
+ @target = target
9
+ end
10
+
11
+ def and_call_original(...)
12
+ @expectation.and_call_original(...)
13
+ self
14
+ end
15
+
16
+ def and_return(*)
17
+ cleanup
18
+ raise MockError, "Cannot call and_return when using expect_receive_and_call_original"
19
+ end
20
+
21
+ def and_raise(*)
22
+ cleanup
23
+ raise MockError, "Cannot call and_raise when using expect_receive_and_call_original"
24
+ end
25
+
26
+ def and_throw(*)
27
+ cleanup
28
+ raise MockError, "Cannot call and_throw when using expect_receive_and_call_original"
29
+ end
30
+
31
+ def and_yield(*)
32
+ cleanup
33
+ raise MockError, "Cannot call and_yield when using expect_receive_and_call_original"
34
+ end
35
+
36
+ def method_missing(name, ...)
37
+ if @expectation.respond_to?(name)
38
+ res = @expectation.public_send(name, ...)
39
+ res.equal?(@expectation) ? self : res
40
+ else
41
+ super
42
+ end
43
+ end
44
+
45
+ def respond_to_missing?(name, include_private = false)
46
+ @expectation.respond_to?(name, include_private) || super
47
+ end
48
+
49
+ private def cleanup
50
+ RSpec::Mocks.space.proxy_for(@target).reset if defined?(::RSpec::Mocks)
51
+ end
52
+ end
53
+
54
+ module ExampleMethods
55
+ def expect_receive_and_call_original(target, method_name)
56
+ expectation = RSpec::Armour.without_restrictions do
57
+ expect(target).to receive(method_name).and_call_original
58
+ end
59
+ ExpectationProxy.new(expectation, target)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RSpec
4
4
  module Armour
5
- VERSION = "0.1.0"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
data/lib/rspec/armour.rb CHANGED
@@ -5,6 +5,7 @@ require "rspec/mocks"
5
5
  require_relative "armour/version"
6
6
  require_relative "armour/checker"
7
7
  require_relative "armour/receive_patch"
8
+ require_relative "armour/expect_and_call_original"
8
9
 
9
10
  module RSpec
10
11
  module Armour
@@ -22,6 +23,8 @@ require "rspec/mocks/matchers/receive"
22
23
  RSpec::Mocks::Matchers::Receive.patch_for_armour!
23
24
 
24
25
  RSpec.configure do |config|
26
+ config.include RSpec::Armour::ExampleMethods
27
+
25
28
  config.around(:each, without_rspec_armour: true) do |example|
26
29
  RSpec::Armour.without_restrictions do
27
30
  example.run
data/quality.sh CHANGED
@@ -7,5 +7,3 @@ echo "Running fasterer..."
7
7
  bundle exec fasterer
8
8
  echo "Running rubocop..."
9
9
  bundle exec rubocop
10
- echo "Running reek..."
11
- bundle exec reek
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
6
+
7
+ gem "rake", "~> 13.0"
@@ -0,0 +1,92 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rspec-armor (0.1.0)
5
+ rspec-armour
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (8.1.3)
11
+ activesupport (= 8.1.3)
12
+ activerecord (8.1.3)
13
+ activemodel (= 8.1.3)
14
+ activesupport (= 8.1.3)
15
+ timeout (>= 0.4.0)
16
+ activesupport (8.1.3)
17
+ base64
18
+ bigdecimal
19
+ concurrent-ruby (~> 1.0, >= 1.3.1)
20
+ connection_pool (>= 2.2.5)
21
+ drb
22
+ i18n (>= 1.6, < 2)
23
+ json
24
+ logger (>= 1.4.2)
25
+ minitest (>= 5.1)
26
+ securerandom (>= 0.3)
27
+ tzinfo (~> 2.0, >= 2.0.5)
28
+ uri (>= 0.13.1)
29
+ base64 (0.3.0)
30
+ bigdecimal (4.1.2)
31
+ concurrent-ruby (1.3.7)
32
+ connection_pool (3.0.2)
33
+ diff-lcs (1.6.2)
34
+ drb (2.2.3)
35
+ i18n (1.15.2)
36
+ concurrent-ruby (~> 1.0)
37
+ json (2.21.1)
38
+ logger (1.7.0)
39
+ minitest (6.0.6)
40
+ drb (~> 2.0)
41
+ prism (~> 1.5)
42
+ prism (1.9.0)
43
+ rake (13.4.2)
44
+ rspec-armour (0.1.0)
45
+ activerecord
46
+ rspec-mocks
47
+ rspec-mocks (3.13.8)
48
+ diff-lcs (>= 1.2.0, < 2.0)
49
+ rspec-support (~> 3.13.0)
50
+ rspec-support (3.13.7)
51
+ securerandom (0.4.1)
52
+ timeout (0.6.1)
53
+ tzinfo (2.0.6)
54
+ concurrent-ruby (~> 1.0)
55
+ uri (1.1.1)
56
+
57
+ PLATFORMS
58
+ ruby
59
+ x86_64-linux
60
+
61
+ DEPENDENCIES
62
+ rake (~> 13.0)
63
+ rspec-armor!
64
+
65
+ CHECKSUMS
66
+ activemodel (8.1.3) sha256=90c05cbe4cef3649b8f79f13016191ea94c4525ce4a5c0fb7ef909c4b91c8219
67
+ activerecord (8.1.3) sha256=8003be7b2466ba0a2a670e603eeb0a61dd66058fccecfc49901e775260ac70ab
68
+ activesupport (8.1.3) sha256=21a5e0dfbd4c3ddd9e1317ec6a4d782fa226e7867dc70b0743acda81a1dca20e
69
+ base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
70
+ bigdecimal (4.1.2) sha256=53d217666027eab4280346fba98e7d5b66baaae1b9c3c1c0ffe89d48188a3fbd
71
+ bundler (4.0.12) sha256=7f8b757d28dfb636e7b24fba2344ac6dd13b5b24f4b46d62573d483f211825ac
72
+ concurrent-ruby (1.3.7) sha256=4412caec3a5ea2e5fdc52076724c071a81f2c0593d83b2ac8cbb8ca63b3151b0
73
+ connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
74
+ diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962
75
+ drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373
76
+ i18n (1.15.2) sha256=00f9eb62412fe593b2a65a97daa75300d37abb8f7202ec748e94b6d46a9dd1b5
77
+ json (2.21.1) sha256=13a43df75d95641443f5702dff350f237164a9d811ff0f2c2800d4d980220583
78
+ logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
79
+ minitest (6.0.6) sha256=153ea36d1d987a62942382b61075745042a2b3123b1cd48f4c3675af9cc7d6f1
80
+ prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
81
+ rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
82
+ rspec-armor (0.1.0)
83
+ rspec-armour (0.1.0) sha256=d03542ac9a6a9d61be9ca2be6f0a550ae19c2f56d2a40b65769cdcbd8cb3a31f
84
+ rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47
85
+ rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
86
+ securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
87
+ timeout (0.6.1) sha256=78f57368a7e7bbadec56971f78a3f5ecbcfb59b7fcbb0a3ed6ddc08a5094accb
88
+ tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b
89
+ uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
90
+
91
+ BUNDLED WITH
92
+ 4.0.12
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "rspec-armor"
5
+ spec.version = "0.1.0"
6
+ spec.authors = ["Harry Lascelles"]
7
+ spec.email = ["harry@harryl.com"]
8
+
9
+ spec.summary = "American-spelling alias for rspec-armour. Please use rspec-armour instead."
10
+ spec.description = <<~MSG
11
+ This gem exists solely to prevent typo-squatting on the American spelling of rspec-armour.
12
+ It installs rspec-armour (British spelling) and does nothing else.
13
+ Please depend on rspec-armour directly.
14
+ MSG
15
+ spec.homepage = "https://github.com/hlascelles/rspec-armour"
16
+ spec.license = "MIT"
17
+ spec.required_ruby_version = ">= 3.2.0"
18
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
19
+ spec.metadata["homepage_uri"] = spec.homepage
20
+ spec.metadata["source_code_uri"] = spec.homepage
21
+ spec.metadata["rubygems_mfa_required"] = "true"
22
+
23
+ spec.files = ["rspec-armor.gemspec"]
24
+
25
+ spec.add_dependency "rspec-armour"
26
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-armour
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harry Lascelles
@@ -151,9 +151,14 @@ files:
151
151
  - Rakefile
152
152
  - lib/rspec/armour.rb
153
153
  - lib/rspec/armour/checker.rb
154
+ - lib/rspec/armour/expect_and_call_original.rb
154
155
  - lib/rspec/armour/receive_patch.rb
155
156
  - lib/rspec/armour/version.rb
156
157
  - quality.sh
158
+ - rspec-armor/Gemfile
159
+ - rspec-armor/Gemfile.lock
160
+ - rspec-armor/Rakefile
161
+ - rspec-armor/rspec-armor.gemspec
157
162
  homepage: https://github.com/hlascelles/rspec-armour
158
163
  licenses:
159
164
  - MIT