Welcome to mirror list, hosted at ThFree Co, Russian Federation.

stub_method_calls.rb « helpers « support « spec - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 45d704958ca0694a1a0db9ea7287d2353621233d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# frozen_string_literal: true

# Used to stud methods for factories where we can't
# use rspec-mocks.
#
# Examples:
#   stub_method(user, :some_method) { |var1, var2| var1 + var2 }
#   stub_method(user, :some_method) { true }
#   stub_method(user, :some_method) => nil
#   stub_method(user, :some_method) do |*args|
#     true
#   end
#
#  restore_original_method(user, :some_method)
#  restore_original_methods(user)
#
module StubMethodCalls
  AlreadyImplementedError = Class.new(StandardError)

  def stub_method(object, method, &block)
    Backup.stub_method(object, method, &block)
  end

  def restore_original_method(object, method)
    Backup.restore_method(object, method)
  end

  def restore_original_methods(object)
    Backup.stubbed_methods(object).each_key { |method, backed_up_method| restore_original_method(object, method) }
  end

  module Backup
    def self.stubbed_methods(object)
      return {} unless object.respond_to?(:_stubbed_methods)

      object._stubbed_methods
    end

    def self.backup_method(object, method)
      backed_up_methods = stubbed_methods(object)
      backed_up_methods[method] = object.respond_to?(method) ? object.method(method) : nil

      object.define_singleton_method(:_stubbed_methods) { backed_up_methods }
    end

    def self.stub_method(object, method, &block)
      raise ArgumentError, "Block is required" unless block_given?

      backup_method(object, method) unless backed_up_method?(object, method)
      object.define_singleton_method(method, &block)
    end

    def self.restore_method(object, method)
      raise NotImplementedError, "#{method} has not been stubbed on #{object}" unless backed_up_method?(object, method)

      object.singleton_class.remove_method(method)
      backed_up_method = stubbed_methods(object)[method]

      object.define_singleton_method(method, backed_up_method) if backed_up_method
    end

    def self.backed_up_method?(object, method)
      stubbed_methods(object).key?(method)
    end
  end
end