【问题标题】:Ruby: const_set outside block?红宝石: const_set 块外?
【发布时间】:2014-04-14 22:40:53
【问题描述】:

我想mock a class with Ruby

如何编写处理样板代码的方法?

以下代码:

module Mailgun

end

module Acani
  def self.mock_mailgun(mock)
    temp = Mailgun
    const_set(:Mailgun, mock)
    p Mailgun
    yield
  ensure
    const_set(:Mailgun, temp)
  end
end

Acani.mock_mailgun('mock') { p Mailgun }

打印:

"mock"
Mailgun

这里发生了什么?为什么Mailgun 是块内的原始值?这是否与 Ruby 绑定有关?

Ruby 版本:2.1.1p76

【问题讨论】:

    标签: ruby mocking block metaprogramming constants


    【解决方案1】:

    尝试将Object. 放在每个const_set 之前。

    问题中的代码已简化。以下是相关代码:

    test/test_helper.rb

    require 'minitest/autorun'
    
    module Acani
      def self.const_mock(const, mock)
        temp = const_get(const)
        const_set_silent(const, mock)
        yield
      ensure
        const_set_silent(const, temp)
      end
    
      private
    
      def self.const_set_silent(const, value)
        temp = $VERBOSE
        $VERBOSE = nil
        Object.const_set(const, value)
      ensure
        $VERBOSE = temp
      end
    end
    

    test/web_test.rb

    require 'test_helper'
    require 'rack/test'
    require_relative '../web'
    
    class AppTest < MiniTest::Test
      include Rack::Test::Methods
    
      def app
        Sinatra::Application
      end
    
      def test_password_reset
        post '/users', {email: 'user1@gmail.com', password: 'password1'}
    
        mailgun_mock = MiniTest::Mock.new
        mailgun_mock.expect(:send, 200, [Hash])
    
        Acani.const_mock(:Mailgun, mailgun_mock) do
          post '/password_resets', {email: 'user1@gmail.com'}
        end
    
        mailgun_mock.verify
        assert_equal 201, last_response.status
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-09
      • 1970-01-01
      相关资源
      最近更新 更多