Code Monkey home page Code Monkey logo

mocktail's People

Contributors

al2o3cr avatar andyw8 avatar calebhearth avatar cutalion avatar jez avatar kevin-j-m avatar searls avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mocktail's Issues

SyntaxError when upgrading from 1.2.0 to 1.2.1

I just upgraded Mocktail from 1.2.0 to 1.2.1 on a project with no other changes and started seeing this error:

Error:
ReactionEventsTest#test_reaction_added_events_are_logged:
SyntaxError: /usr/local/bundle/gems/mocktail-1.2.1/lib/mocktail/imitates_type/makes_double/declares_dry_class.rb:60: syntax error, unexpected '=', expecting ')'
            ->( = ((__mocktail_default_args ||...
                ^
/usr/local/bundle/gems/mocktail-1.2.1/lib/mocktail/imitates_type/makes_double/declares_dry_class.rb:60: syntax error, unexpected ']', expecting literal content or terminator or tSTRING_DBEG or tSTRING_DVAR
...ocktail_default_args ||= {})[:] = nil), &blk) do

The corresponding line in my test suite that this is tied to looks like:

slack_client_mock = Mocktail.of_next(Slack::Web::Client)

The way I'm getting around this is by wrapping calls to the third party Slack library in a PORO and mocking instances of said PORO, but wanted to open this issue just in case.

Ruby 2.7.4 Test Failure

The gemspec mentions 2.7 as the minimum ruby version; however, running the test suite does not appear to pass (at least for me, locally) when using 2.7.4.

Reproduction Steps

  1. Set ruby version to 2.7.4
  2. Run tests (I did so with rake)

Expected

Tests Pass

Actual

  1) Error:
VerifyTest#test_uses_a_captor_for_a_complex_arg:
ArgumentError: ArgumentError
    /mocktail/lib/mocktail/handles_dry_call/validates_arguments.rb:41:in `validate'
    /mocktail/lib/mocktail/handles_dry_call.rb:14:in `handle'
    /mocktail/lib/mocktail/imitates_type/makes_double/declares_dry_class.rb:42:in `block (2 levels) in define_double_methods!'
    /mocktail/test/safe/verify_test.rb:135:in `test_uses_a_captor_for_a_complex_arg'

61 runs, 295 assertions, 0 failures, 1 errors, 0 skips

Notes

I also ran the tests locally with ruby 3.0.1, and tests passed for me then.

Missing from README: What is this? Why should I care?

I am intrigued in concept by the idea of mocktail, but I can't easily understand what it is. Ideally, I'd see a concise description of the problem, and how mocktail solves that. Perhaps a quick code example, showing before/after mocktail could help?

There's nothing about this in the README, and while there seems to be solid docs (nice work!) on implementing mocktail etc, they seem to make me get into the details before I can understand whether it's worth that effort.

Infinite loop when used on objects that define `==`

I only briefly dug into the cause, but wasn't able to find it. Posting a repro here in case anybody else cares to look.

require "mocktail"

class Foobar < Sequel::Model
  def name
    "Bar"
  end
end

foobar = Mocktail.of(Foobar)
Mocktail.stubs { foobar.name }.with { "Foobar" }
Mocktail.explain(foobar)

Run with sequel mock://sqlite <file.rb>

Output

I, [2021-11-15T02:43:07.555625 #52542]  INFO -- : (0.000001s) SELECT * FROM `foobars` LIMIT 0
/usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/share/determines_matching_calls.rb:4:in `determine': stack level too deep (SystemStackError)
        from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb:11:in `block in find'
        from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb:10:in `each'
        from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb:10:in `find'
        from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb:10:in `find'
        from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/handles_dry_call/fulfills_stubbing.rb:22:in `satisfaction'
        from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/handles_dry_call/fulfills_stubbing.rb:12:in `fulfill'
        from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/handles_dry_call.rb:16:in `handle'
        from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/imitates_type/makes_double/declares_dry_class.rb:45:in `block (2 levels) in define_double_methods!'
         ... 9981 levels...
        from /usr/local/bundle/gems/sequel-5.50.0/bin/sequel:260:in `each'
        from /usr/local/bundle/gems/sequel-5.50.0/bin/sequel:260:in `<top (required)>'
        from /usr/local/bundle/bin/sequel:23:in `load'
        from /usr/local/bundle/bin/sequel:23:in `<main>'

RSpec must require Mocktail before adding DSL?

After adding Mocktail and following the README instructions to configure RSpec, I receive the following error when attempting to run any tests, unless I require "mocktail" in the spec_helper.rb:

An error occurred while loading spec_helper.
Failure/Error: config.include Mocktail::DSL

NameError:
  uninitialized constant Mocktail

I confirmed I'm also seeing the same behavior when adding Mocktail to an existing (and private) Rails application.

If that seems reasonable and expected, I can push PR that updates the README to say that it should be included, but in case I'm doing something silly, I figured I'd bring this up as an issue first.

I can also try to replicate on a fresh rails app and/or gem, if you'd like different/more easily reproducible replication steps.

[Discussion] Refuting stubbed methods?

First off before anything, thanks for this lovely gem! I've always been fairly frustrated with mocking libraries but this one does it really nicely.

This is more of a discussion starter than anything else, but what are your thoughts on including a Mocktail.verify_not or something similar? (Not using #refute since that would clash with Minitest::Assertions#refute.)

While it's true that we can easily accomplish this with something like:

assert_raises(Mocktail::VerificationError) do
  Mocktail.verify do
    # ...
  end
end

I just think it'd just be really nice if there was a method for this, kind of in the same Ruby spirit as Minitest having #assert and #refute, Rails having things like #second, #third, and so on.

AmbiguousDemonstrationError when incorrectly using of_next vs replace and class has matching instance method

Given a class which has matching instance and class methods, if a test incorrectly calls Mocktail.of_next instead of Mocktail.replace then tries to demonstrate a call to the method, this error is raised:

`stubs` & `verify` expect exactly one invocation of a mocked method, but 2 were detected.
As a result, Mocktail doesn't know which invocation to stub or verify. 
(Mocktail::AmbiguousDemonstrationError)

I'd expect there to be 0 invocations detected, but even better I'd love to be told that I'm not demonstrating using anything that's been mocked yet.

Here's a basic reproduction:

ambiguous.rb:

require "mocktail"

class Fighter
  def self.weapon
    new.weapon
  end

  def weapon
    "sword"
  end
end

Mocktail.of_next(Fighter)

Mocktail.stubs { Fighter.weapon }.with { nil }

$ ruby ambiguous.rb

Y'all got some strategy for mocking ActiveRecord associations?

I have a method on an AR model that calls a method on an associated model and does some biz with the result. I'd like to mock it but I can't seem use a Mocktail to replace an ActiveRecord association. Y'all got thoughts?

So here's my lil example script:

# frozen_string_literal: true
require 'bundler/inline'
require 'minitest/autorun'
require 'mocktail'

gemfile(true) do
  source 'https://rubygems.org'

  gem 'rails', '~> 7.0.4'
  gem 'sqlite3'
  gem 'mocktail'
end

require 'rails/all'
database = 'development.sqlite3'

ENV['DATABASE_URL'] = "sqlite3:#{database}"
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: database)
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
  create_table :posts, force: true do |t|
  end

  create_table :comments, force: true do |t|
    t.integer :post_id
  end
end

class Post < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :post
end

class MocktailTest < ActiveSupport::TestCase
  include Mocktail::DSL

  test "associating a mocktail" do
    post = Mocktail.of(Post)
    Comment.new(post: post)
  end
end

which when ran hits me with a:

Minitest::UnexpectedError: NoMethodError: undefined method `primary_key' for #<Class for mocktail of Post:0x0000000106e3b4b0>
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/reflection.rb:317:in `primary_key'
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/reflection.rb:744:in `association_primary_key'
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/associations/belongs_to_association.rb:130:in `primary_key'
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/associations/belongs_to_association.rb:122:in `replace_keys'
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/associations/belongs_to_association.rb:93:in `replace'
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/associations/singular_association.rb:19:in `writer'
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/associations/builder/association.rb:112:in `post='
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activemodel-7.0.4.3/lib/active_model/attribute_assignment.rb:49:in `public_send'
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activemodel-7.0.4.3/lib/active_model/attribute_assignment.rb:49:in `_assign_attribute'
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/attribute_assignment.rb:21:in `block in _assign_attributes'
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/attribute_assignment.rb:13:in `each'
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/attribute_assignment.rb:13:in `_assign_attributes'
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activemodel-7.0.4.3/lib/active_model/attribute_assignment.rb:34:in `assign_attributes'
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/core.rb:468:in `initialize'
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/inheritance.rb:75:in `new'
    /Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/inheritance.rb:75:in `new'
    /Users/dazmin/RubymineProjects/mocktail_rails_test/mocktail_rails_test.rb:42:in `block in <class:MocktailTest>'
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/reflection.rb:317:in `primary_key'
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/reflection.rb:744:in `association_primary_key'
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/associations/belongs_to_association.rb:130:in `primary_key'
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/associations/belongs_to_association.rb:122:in `replace_keys'
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/associations/belongs_to_association.rb:93:in `replace'
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/associations/singular_association.rb:19:in `writer'
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/associations/builder/association.rb:112:in `post='
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activemodel-7.0.4.3/lib/active_model/attribute_assignment.rb:49:in `public_send'
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activemodel-7.0.4.3/lib/active_model/attribute_assignment.rb:49:in `_assign_attribute'
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/attribute_assignment.rb:21:in `block in _assign_attributes'
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/attribute_assignment.rb:13:in `each'
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/attribute_assignment.rb:13:in `_assign_attributes'
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activemodel-7.0.4.3/lib/active_model/attribute_assignment.rb:34:in `assign_attributes'
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/core.rb:468:in `initialize'
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/inheritance.rb:75:in `new'
/Users/dazmin/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.3/lib/active_record/inheritance.rb:75:in `new'
/Users/dazmin/RubymineProjects/mocktail_rails_test/mocktail_rails_test.rb:42:in `block in <class:MocktailTest>'

Process finished with exit code 1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.