2016-12-29 2 views
0

실패한 Rspec 테스트를 작성하려고합니다. 실제 테스트는 훨씬 긴 코드와 관련되어 있지만 문제를 테스트하는 클래스 메소드로 좁혔습니다.Rspec이 클래스 메소드를 전달하지만 인스턴스 메소드가 실패합니다.

여기 RSpec에있는 시험입니다 :

context "For '.CASH.' as a stock" do 
    let!(:cash) { FactoryGirl.create(:stock, symbol: '.CASH.', name: 'cash', status: 'Available') } 

    describe "When update_stock runs on it" do 
    it "should still have an 'Available' status" do 
     # status should be 'Error' and test should fail 
     Stock.change_to_error 
     expect(cash.status).to eq('Available') 
    end 
    end 
end 

이것은 Stock.rb에서 모델 클래스 메소드를 테스트하고있다 : 어떤 이유

def self.change_to_error 
    self.all.each do |stock| 
    stock.status = "Error" 
    stock.save 
    end 
end 

,이 전달합니다. 내가 인스턴스 메서드를 사용하도록 변경하는 경우에는, 그것이 같은 실패해야 : stock_spec.rb가 인스턴스 메소드로 변경 한 경우

:

context "For '.CASH.' as a stock" do 
let!(:cash) { FactoryGirl.create(:stock, symbol: '.CASH.', name: 'cash', status: 'Available') } 

    describe "When update_stock runs on it" do 
    it "should still have an 'Available' status" do 
     # status should be 'Error' and test should fail 
     cash.change_to_error 
     expect(cash.status).to eq('Available') 
    end 
    end 
end 

그리고 stock.rb 클래스 메서드는 인스턴스로 설정되어있는 경우 방법 :

def change_to_error 
    self.status = 'Error' 
    self.save 
end 

이것은 통과합니다. 불행히도 DB의 모든 주식을 업데이트하고 싶기 때문에 인스턴스 메서드 대신 클래스 메서드를 사용해야합니다. "Change_to_error"메소드는 문제를 파악하기위한 것입니다. 그것은 실패 할 때 클래스 메서드로 전달하는 이유를 누구나 알 수 있습니까? 하지만 인스턴스 메서드를 사용할 때 제대로 실패합니까?

효과적으로, 클래스 메소드는 '현금'의 상태 속성을 변경하지 않지만 인스턴스 메소드는 변경됩니다. 나는 그것이 왜 일어나고 있는지 모른다.

참고로, 나는 RSpec에 레일을

+1

'stock.save'를'stock.save!'로 변경할 수 있습니까? 잘못된 것이 있으면 예외가 발생합니다. – 31piy

+0

나는 그것을 시험해 보았다. 도와주지 않았어. 다른 아이디어? – HoodieOnRails

+0

'Stock.find_each {| stock | stock.update_column (: 상태, '오류')}'. – 31piy

답변

1

솔루션을 사용하고 있습니다 : 필요 'Stock.change_to_error'후 'cash.reload'을 넣고 기대 라인 전에 할 수 있습니다.

let!을 사용하면 테스트 전에 개체가 만들어집니다. 오브젝트 외부에서 기본 데이터를 갱신하면 인스턴스가 오래되게됩니다. reload을 호출하면 ActiveRecord가 강제로 데이터베이스에서 새로 고칩니다.


당신이 let를 사용

, RSpec에,이 경우에, 당신은 속성을 참조 처음으로까지 cash을 블록을 호출하지 않습니다. 따라서 첫 번째 예제에서는 change_to_error을 전혀 기록하지 않고 expect이라는 행에 생성되는 레코드 인 cash에서 상태를 확인합니다. 두 번째 예에서는 cash 개체가 만들어지고 오류로 변경됩니다. 이 문제를 확인하기 위해 로그를 꼬리를 권합니다.

let!으로 변경하면 RSpec은 모든 예가 실행되기 전에 개체를 만듭니다. 또 다른 대안은 생성 된 모든 레코드에서 change_to_error을 호출하기 전에 예제에서 cash을 참조하는 것입니다.

+0

불행히도, 그것은 작동하지 않았다. before 루프를 사용하고 let (: cash) 대신 @cash 인스턴스 변수를 사용하더라도 작동하지 않습니다. 다른 아이디어? – HoodieOnRails

+0

이것이 문제를 해결하지는 못했지만 위의 코드에서 여러분의 관찰이 정확하다는 것을 알게되었습니다. – HoodieOnRails

+1

상태를 확인하기 전에 '현금'을 다시로드 해보십시오. let!을 사용 했으므로 모델이 생성되고 클래스 메소드가 기본 모델을 변경하지만 'cash' 인스턴스에는 여전히 캐시 된 값이있을 수 있습니다. 'cash.reload! '를 시도한 다음 상태를 확인하십시오. – mroach

관련 문제