lib/mocktail.rb in mocktail-1.2.3 vs lib/mocktail.rb in mocktail-2.0.0

- old
+ new

@@ -1,11 +1,25 @@ +require "pathname" + +if defined?(Mocktail::TYPED) + if eval("Mocktail::TYPED", binding, __FILE__, __LINE__) + warn "`require \"mocktail\"' was called, but Mocktail was already required as `require \"mocktail/sorbet\"', so we're NOT going to load it to avoid constants from being redefined. If you want to use Mocktail WITHOUT sorbet runtime checks, remove whatever is requiring `mocktail/sorbet'." + else + warn "`require \"mocktail/sorbet\"' was called, but Mocktail was already required as `require \"mocktail\"', so we're NOT going to load it to avoid constants from being redefined. If you want to use Mocktail WITH sorbet runtime checks, remove whatever is requiring `mocktail'." + end + return +end + +require_relative "mocktail/initialize_based_on_type_system_mode_switching" + require_relative "mocktail/collects_calls" require_relative "mocktail/debug" require_relative "mocktail/dsl" require_relative "mocktail/errors" require_relative "mocktail/explains_thing" require_relative "mocktail/explains_nils" +require_relative "mocktail/grabs_original_method_parameters" require_relative "mocktail/handles_dry_call" require_relative "mocktail/handles_dry_new_call" require_relative "mocktail/imitates_type" require_relative "mocktail/initializes_mocktail" require_relative "mocktail/matcher_presentation" @@ -21,25 +35,49 @@ require_relative "mocktail/value" require_relative "mocktail/verifies_call" require_relative "mocktail/version" module Mocktail + extend T::Sig + extend DSL + BASE_PATH = (Pathname.new(__FILE__) + "..").to_s + # Returns an instance of `type` whose implementation is mocked out + def self.of(type) ImitatesType.new.imitate(type) end # Returns an instance of `klass` whose implementation is mocked out AND # stubs its constructor to return that fake the next time klass.new is called + def self.of_next(type, count: 1) - ReplacesNext.new.replace(type, count) + count ||= 1 + if count == 1 + ReplacesNext.new.replace_once(type) + elsif !Mocktail::TYPED || T::Private::RuntimeLevels.default_checked_level == :never + ReplacesNext.new.replace(type, count) + else + raise TypeCheckingError.new <<~MSG + Calling `Mocktail.of_next()' with a `count' value other than 1 is not supported when + type checking is enabled. There are two ways to fix this: + + 1. Use `Mocktail.of_next_with_count(type, count)' instead, which will always return + an array of fake objects. + + 2. Disable runtime type checking by setting `T::Private::RuntimeLevels.default_checked_level = :never' + or by setting the envronment variable `SORBET_RUNTIME_DEFAULT_CHECKED_LEVEL=never' + MSG + end end - # See lib/mocktail/dsl.rb - define_singleton_method :stubs, DSL.instance_method(:stubs) - define_singleton_method :verify, DSL.instance_method(:verify) + # An alias of of_next that always returns an array of fakes + def self.of_next_with_count(type, count) + ReplacesNext.new.replace(type, count) + end + def self.matchers MatcherPresentation.new end def self.captor @@ -50,10 +88,11 @@ RegistersMatcher.new.register(matcher) end # Replaces every singleton method on `type` with a fake, and when instantiated # or included will also fake instance methods + def self.replace(type) ReplacesType.new.replace(type) nil end @@ -70,16 +109,18 @@ end # An alias for Mocktail.explain(double).reference.calls # Takes an optional second parameter of the method name to filter only # calls to that method + def self.calls(double, method_name = nil) - CollectsCalls.new.collect(double, method_name) + CollectsCalls.new.collect(double, method_name&.to_sym) end # Stores most transactional state about calls & stubbing configurations # Anything returned by this is undocumented and could change at any time, so # don't commit code that relies on it! + def self.cabinet Thread.current[:mocktail_store] ||= Cabinet.new end end