2016-02-22 23 views
0

我測試類的初始化塊如下expect_any_instance_of與對象參數

class A 
    attr_accessor :client 

    def initialize(options, configuration) 
    self.client = B.new(options) 
    config = C.new(
     url: configuration[:url], 
     headers: configuration[:headers], 
     username: configuration[:username], 
     password: configuration[:password] 
    ) 
    client.configure(config) 
    end 
end 

class C 
    def initialize(options) 
    # does something with options hash 
    end 
end 

class B 
    def initialize(options) 
    # does something with options hash 
    end 

    def configure(config) 
    # some configuration with config object 
    end 
end 

我的測試情況如下:

let(:options) { 
    { 
    force_basic_auth: true 
    } 
} 

let(:configuration) { 
    { 
    url: 'https://localhost:3000', 
    headers: { awesome: true }, 
    username: 'test', 
    password: 'pass' 
    } 
} 

let(:api_config) { 
    C.new(configuration) 
} 

it 'configures object with passed params' do 
    expect_any_instance_of(B).to receive(:configure) 
    .with(api_config) 

    A.new(
    options, 
    configuration 
) 
end 

這失敗我測試的情況下,因爲在創建該對象初始化塊與我在期望中使用的api_config的object_id有不同的object_id

-[#<C:0x00000002b51128 @url="https://localhost:3000", @headers={:awesome=>true}, @username="test", @password="pass">] 
    +[#<C:0x00000002a1b628 @url="https://localhost:3000", @headers={:awesome=>true}, @username="test", @password="pass">] 

看到這種失敗我在想是否是在初始化塊中直接傳遞這些對象的最佳做法。我的意思是我可以通過直接在初始化塊中傳遞對象來修復它。 有許多函數正在初始化A類,因爲我正在以當前方式進行散列選項傳遞。

有沒有一種方法來期望在rspec中傳遞的對象的內容,而不是驗證對象是否一樣?直接在初始化中傳遞對象是一種更好的方法嗎?

+0

什麼是'B'?什麼是「配置」?他們是一樣的嗎? –

+0

@UriAgassi對不起,我無法粘貼確切的代碼,所以我改變了類名。我已經添加了問題所需的'B'和'C'類的最小定義。如果我錯過了其他任何事,請告訴我。謝謝:) –

+0

不應''api_config'類型'C'? –

回答

1

您可以定義任意期望的處理來檢查檢查參數的值(見here):

it 'configures object with passed params' do 
    expect_any_instance_of(B).to receive(:configure) do |config| 
    expect(config).to be_a(C) 
    expect(config.url).to eq(configuration[:url]) 
    expect(config.headers).to eq(configuration[:headers]) 
    # ... 
    end 

    A.new(
    options, 
    configuration 
) 
end 
+0

我在本地嘗試過,'config'是'B'的對象而不是'C'的對象。 –

+0

我不確定我是否理解你的評論... –

+0

我需要比較傳遞給配置方法的對象和散列配置的內容。 –

0

您想要配置的散列(而不是對象)B.configure(config)下,讓你的類必須改變稍微適應。

類文件

class A 
    attr_accessor :client 

    def initialize(options, configuration) 
    self.client = B.new(options) 
    config = C.new(
     url: configuration[:url], 
     headers: configuration[:headers], 
     username: configuration[:username], 
     password: configuration[:password] 
    ) 
    client.configure(config.options) 
    end 
end 

class C 
    attr_reader :options 

    def initialize(options) 
    @options = options 
    end 
end 

class B 
    def initialize(options) 
    # does something with options hash 
    end 

    def configure(config) 
    # some configuration with config object 
    end 
end 

這是你的RSpec的代碼是什麼樣子。

describe do 
    let(:options) do 
    { 
     force_basic_auth: true 
    } 
    end 

    let(:configuration) do 
    { 
     url: 'https://localhost:3000', 
     headers: { awesome: true }, 
     username: 'test', 
     password: 'pass' 
    } 
    end 

    let(:my_a_object) { A.new(options, configuration) } 
    let(:my_b_object) { B.new(options) } 

    it 'configures object with passed params' do 
    allow(B).to receive(:new).with(options).and_return(my_b_object) 

    expect(my_b_object).to receive(:configure).with(configuration) 
    my_a_object 
    end 
end