2014-06-17 32 views
1

我跑在rspec的集成測試和測試不斷billed_for扔了一個未定義的方法:未定義的方法在RSpec的測試

「未定義的方法billed_for零:NilClass」

require 'user' 

describe "Integration" do 
    let(:user) { User.new(voucher) } 

    context 'no voucher' do 
    let(:voucher) { nil } 

    it 'should bill default price all the time' do 
     user.bill 
     expect(user.orders[0].billed_for).to eql 6.95 
    end 
    end 
end 

我有一個非常小的用戶類到目前爲止

require 'order' 
require 'voucher' 

class User 
    attr_accessor :voucher, :orders 

    def initialize(orders = [], voucher = nil) 
    @voucher = voucher 
    @orders = [orders] 
    end 

    def bill 
    new_order = Order.new(self) 
    @orders << new_order 
    end 
end 

和同樣小訂單類:

class Order 
    DEFAULT_PRICE = 6.95 

    attr_accessor :user 

    def initialize(user) 
    @user = user 
    end 

    def billed_for 
    price = DEFAULT_PRICE 
    user.orders.each do |order| 
     price - order.billed_for 
    end 
    price 
    end 
end 

什麼是最困惑我是這一行

user.orders[0].billed_for 

時,我認爲它通過一個新的用戶級設置這讓我再訪問訂單哈希在用戶的散列然後我訪問訂單類中的billed_for方法。

當我GOOGLE了這個問題,它指向使用self關鍵字不工作。

如果有人能在正確的方向指向我,這簡直太好

編輯:

雅各布小號親切指着我的測試,因爲在我的陣列零條目的失敗。

對此的快速修復只是爲了運行緊湊的功能來刪除無條目。

總是打開更好的解決方案。

編輯2:

let(:user) { User.new(voucher) } 

context 'no voucher' do 
    let(:voucher) { nil } 

    it 'should bill default price all the time' do 
     user.bill 
     expect(user.orders[0].billed_for).to eql 6.95 
     ... ... 
    end 
end 

context 'vouchers' do 
    describe 'default vouchers' do 
    let(:voucher) { Voucher.create(:default, credit: 15) } 

    it 'should not bill user if has a remaining credit' do 
     user.bill 
     expect(user.orders[0].billed_for).to eql 0.0 
     ... ... 
    end 
    end 

感謝您的幫助迄今。我還開了一個額外的線程,因爲我有一些其他類似的問題

Accessing variables of other classes

+0

在測試中是否曾經傳遞給''用戶'初始化方法?似乎初始化應該將其設置爲一個空數組,而不是傳入值? – house9

+0

我已經添加了一個測試流程的例子!它看起來像訂單隻有用戶類啓動 – user3750194

回答

5

當你實例化你的user,您使用

let(:user) { User.new(voucher) } 

voucher

let(:voucher) { nil } 
定義爲 nil

換句話說,你用實例化你的user變量。

User構造函數簽名

def initialize(orders = [], voucher = nil) 

這樣做User.new(nil)你的orders參數設置爲nilvouchernil,但是這是在默認情況下)。然後,您的構造函數繼續並創建一個實例變量,它將設置爲[orders] - 在本例中與[nil]相同。

然後,您的測試繼續進行,並向@orders陣列添加新訂單,這很好,並且會使您的@orders陣列包含[nil, instance_of(Order)]

最後,測試嘗試將billed_for方法發送到orders陣列中的第一個元素:user.orders[0].billed_for。該訂單數組包含[nil, instance_of(Order)]的第一要素是nil,所以你實際上是在你的規範,這將導致您看到的錯誤調用

nil.billed_for 

我想你可能會更接近你要找的東西,因爲在實例化User時沒有將voucher轉換爲orders參數。此外,您的測試可能要檢查最後一個元素,即user.orders.last而不是user.orders[0]。而且我懷疑你可能偶爾會遇到一些改進。

+0

它總是非常簡單。非常感謝。我應該提到這是一個編碼練習,所以我無法改變單位規格!但是,謝謝你這樣一個詳細的答案。 你的意思是不是按順序而不是憑證?我試圖想到在初始化器中不創建數組的好方法,但我不確定。如果我在用另一種語言思考,我可能會創建一個空數組而不是零值,或者確保零值被跳過等等。我可能會打擾你在正確的方向上再捅一捅嗎? – user3750194

+0

我想我想說的是什麼纔是避免此初始化問題的最佳方法?我想,在構造函數之外創建數組將是一個開始,但不知道在哪裏...... – user3750194

+0

將命令傳遞給初始化器非常好。不過,您希望將它分配給實例變量,而不是@orders = [orders]',而@order = orders'。後者會將訂單數組包裝到另一個數組中,這不是您想要的。 –

相關問題