Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Creates stub classes from any ActiveRecord model.
By using stubs in your tests you don't need to load Rails or the database, sometimes resulting in a 10x speed improvement.
ActiveMocker analyzes the methods and database columns to generate a Ruby class file.
The stub file can be run standalone and comes included with many useful parts of ActiveRecord.
Stubbed out methods contain their original argument signatures or ActiveMocker's friendly code can be brought over in its entirety.
Mocks are regenerated when the schema is modified so your mocks won't go stale, preventing the case where your unit tests pass but production code fails.
Examples from a real app
Finished in 1 seconds
374 examples, 0 failures
"Mocking ActiveRecord with ActiveMocker" by Envy
Ask a question in the chat room.
Add this line to your application's Gemfile:
group :development, :test do
gem 'active_mocker'
end
It needs to be in development as well as test groups, as the development environment is where mocks will be generated. Then execute:
$ bundle
Or install it yourself as:
$ gem install active_mocker
See example_rails_app for complete setup.
Running this rake task builds/rebuilds the mocks. It will be ran automatically after every schema modification. If the model changes, this rake task needs to be called manually. You could add a file watcher for when your models change and have it run the rake task.
rake active_mocker:build
#db/schema.rb
ActiveRecord::Schema.define(version: 20140327205359) do
create_table "people", force: true do |t|
t.integer "account_id"
t.string "first_name", limit: 128
t.string "last_name", limit: 128
t.string "address", limit: 200
t.string "city", limit: 100
end
end
#app/models/person.rb
class Person < ActiveRecord::Base
belongs_to :account
def self.bar(name, type=nil)
puts name
end
end
require 'rspec'
require 'active_mocker/rspec_helper'
require 'spec/mocks/person_mock'
require 'spec/mocks/account_mock'
describe 'Example', active_mocker:true do
before do
Person.create # stubbed for PersonMock.create
end
end
active_mocker:true
will stub any ActiveRecord model Constants for Mock classes in an it
or a before/after(:each)
. This removes any need for dependency injection. Write tests and code like you would normally.before(:all)
, after(:all)
use active_mocker.find('ClassName')
.after(:all)
. To clean state by yourself, use active_mocker.delete_all
.Person.column_names
=> ["id", "account_id", "first_name", "last_name", "address", "city"]
person = Person.new( first_name: "Dustin",
last_name: "Zeisler",
account: Account.new )
=> "#<PersonMock id: nil, account_id: nil, first_name: "Dustin", last_name: "Zeisler", address: nil, city: nil>"
person.first_name
=> "Dustin"
(After rake db:migrate
is called the mocks will be regenerated.)
#db/schema.rb
ActiveRecord::Schema.define(version: 20140327205359) do
create_table "people", force: true do |t|
t.integer "account_id"
t.string "f_name", limit: 128
t.string "l_name", limit: 128
t.string "address", limit: 200
t.string "city", limit: 100
end
end
Person.new(first_name: "Dustin", last_name: "Zeisler")
=>#<UnknownAttributeError unknown attribute: first_name >
If you want to create a custom set of records that is not part of the global collection for model. (ie. for stubbing in a test)
User::ScopeRelation.new([User.new, User.new])
This gives the full query API (ie. find_by
, where
, etc).
This is not a feature available in ActiveRecord, so do not include this where you intend to swap for ActiveRecord.
Use theses defaults if you are starting fresh
ActiveMocker::LoadedMocks.features.enable(:timestamps)
ActiveMocker::LoadedMocks.features.enable(:delete_all_before_example)
ActiveMocker::LoadedMocks.features.enable(:stub_active_record_exceptions)
Enables created_at
and updated_at
to be updated on save and create
When using "active_mocker/rspec_helper", it deletes all records from all mocks before each example.
When requiring "active_mocker/rspec_helper", and adding active_mocker: true
to the describe
metadata, these errors will be auto stubbed:
Adding the comment ActiveMocker.safe_methods
at the top of a class marks it as safe to copy to the mock.
Be careful. It should not contain anything that ActiveMocker cannot run.
# ActiveMocker.safe_methods(scopes: [], instance_methods: [:full_name], class_methods: [])
class User
def full_name
"#{first_name} + #{last_name}"
end
end
Verifying doubles is a stricter alternative to normal doubles that provides guarantees about what is being verified. When using verifying doubles, RSpec will check if the methods being stubbed are actually present on the underlying object if it is available. rspec-mocks/docs/verifying-doubles
RSpec.configure do |config|
config.mock_framework = :rspec
config.mock_with :rspec do |mocks|
mocks.verify_doubled_constant_names = true
mocks.verify_partial_doubles = true
end
end
Person.bar('baz')
=> NotImplementedError: ::bar is not Implemented for Class :PersonMock. To continue stub the method.
allow(Person).to receive(:bar) do |name, type=nil|
"Now implemented with #{name} and #{type}"
end
Person.bar('foo', 'type')
=> "Now implemented with foo and type"
(Requires a regeneration of the mocks files.)
#app/models/person.rb
class Person < ActiveRecord::Base
belongs_to :account
def self.bar(name)
puts name
end
end
Person.bar('foo', 'type')
=> ArgumentError: wrong number of arguments (2 for 1)
#app/models/person.rb
class Person < ActiveRecord::Base
belongs_to :account
def self.foo(name, type=nil)
puts name
end
end
allow(Person).to receive(:bar) do |name, type=nil|
"Now implemented with #{name} and #{type}"
end
=> RSpec::Mocks::MockExpectationError: PersonMock does not implement: bar
ActiveMocker::Config.disable_modules_and_constants = true
class Person < ActiveRecord::Base
CONSTANT_VALUE = 13
end
PersonMock::CONSTANT_VALUE
=> 13
NotImplementedError
. Stub the method with a value to continue.require "active_mocker/rspec_helper"
active_mocker.delete_all # Delete all records from loaded mocks
active_mocker.find("User") # Find a mock by model name. Useful in before(:all)/after(:all) where automatic constant stubbing is unavailable.
active_mocker.mocks.except("User").delete_all # Delete all loaded mock expect the User mock.
See Documentation for a complete list of methods and usage.
Class Methods - docs
Query Methods - docs
Relation Methods - docs
instance methods - docs
has_one/belongs_to/has_many
#save
. Beware of this difference.id
. If this is causing a problem, feel free to open an issue (or even better, a PR =)).Thanks to Jeff Olfert for being my original inspiration for this project.
Your contributions are welcome!
git checkout -b my-new-feature
)git commit -am 'Add some feature'
)git push origin my-new-feature
)FAQs
Unknown package
We found that active_mocker demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.