2013-07-29 15 views
6

Czy mogę wiedzieć, jak metoda skrótowa w metodzie tworzenia kontrolera? Muszę napisać specyfikację, ale mam te błędy. Muszę sprawdzić metodę create w kontrolerze, aby wykonać metodę validate_fbid przed utworzeniem nowego rekordu firmy w modelu.Rspec: Metoda skrótowa znajdująca się w kontrolerze

Błąd:

1) Companies new company create with valid information#validate_fbid should have correct parameters and return value 
Failure/Error: CompaniesController.create.should_receive(:validates_fbid).with(company) 
NoMethodError: 
    undefined method `create' for CompaniesController:Class 
# ./spec/requests/companies_spec.rb:38:in `block (5 levels) in <top (required)>' 

    2) Companies new company create with valid information#validate_fbid should fbid validation passed 
Failure/Error: CompaniesController.create.stub(:validates_fbid).and_return('companyid') 
NoMethodError: 
    undefined method `create' for CompaniesController:Class 
# ./spec/requests/companies_spec.rb:43:in `block (5 levels) in <top (required)>' 

CompaniesController

def create 
company = Company.new(params[:company]) 
verifyfbid = validate_fbid(company) 

if verifyfbid != false 
    if company.fbid.downcase == verifyfbid.downcase 
     if company.save 
      @message = "New company created." 
      redirect_to root_path 
     else 
      @message = "Company create attempt failed. Please try again." 
      render 'new' 
     end 
    else 
     @message = "Company create attempt failed. Invalid facebook id." 
     render 'new' 
    end 
else 
    @message = "Company create attempt failed. No such facebook id." 
    render 'new'    
    end    
end 

    private 
    def validate_fbid(company) 
    uri = URI("http://graph.facebook.com/" + company.fbid) 
    data = Net::HTTP.get(uri) 
    username = JSON.parse(data)['username']  
    if username.nil? 
    return false 
    else 
    "#{username}" 
    end 
end 

Wnioski/companies_spec.rb

context "#validate_fbid" do    
     #validate fbid 
     let(:company){ Company.new(name:'Example Company', url: 'www.company.com', fbid: 'companyid', desc: 'Company desc')} 

     it "should have correct parameters and return value" do 
      CompaniesController.create.should_receive(:validates_fbid).with(company) 
           .and_return('companyid') 
     end 

     it "should fbid validation passed" do    
      CompaniesController.create.stub(:validates_fbid).and_return('companyid') 
      company.fbid.should_not be_nil 
      company.fbid.should == 'companyid' 
      company.save 
      expect { click_button submit }.to change(Company, :count).by(1) 
     end            
    end  

Odpowiedz

15

Nie chcesz skrótową metody, gdy jest przedmiotem swojej przypadek testowy

context "#validate_fbid" do 
    #test the function here 
    #don't stub 
end 

podczas testowania działania stworzyć w sterowniku, można skrótową „validate_fbid”

describe "post create" do 
    ... 
    CompaniesController.any_instance.stub(:validates_fbid).and_return('companyid') 
    ... 
end 

Nadzieję, że to pomaga.

+10

'allow_any_instance_of (CompaniesController) .W celu otrzymania (: validates_fbid).and_return ('companyid') 'dla Rspec3 – ryan2johnson9

5

Kod jest trudny do sprawdzenia, zwykle dlatego, że jest skomplikowany.

Należy byłaby to kod ten sposób:

  • ruch logika weryfikacja do nowej „klasy usług”, który ma jeden obowiązek weryfikacji firmy na facebooku
  • uczyni funkcjonalność weryfikacja niezależna od warstwy internetowej i znacznie łatwiej testować
  • make spec klasy usług, które będą testować ten kod w izolacji (bez sterowników)
  • porządki kontrolera logiki - don” t chcą mieć logiki wewnątrz kontrolerów (zasada: jeden poziom zagnieżdżenia max)
  • spec regulatora będzie łatwiejsze, jak również

Kod kontroler może wyglądać następująco:

def create 
    company = Company.new(params[:company]) 
    verified = FbCompanyVerifier.new.verify(company) 

    if verified and company.save 
    # success logic 
    else 
    # fail logic 
    end 
end 
+0

Cześć, dziękuję za odpowiedź. Czy oznacza to, że muszę utworzyć klasę FbCompanyVerifier, która ma również metodę "new" i "verify"? Przypuszczam, że nie mogę utworzyć klasy na stronie kontrolera, więc w którym folderze powinienem utworzyć "FbCompanyVerifier"? Dziękuję za wyjaśnienie. Jestem bardzo nowy w tym. –

+0

Popraw - pełna klasa z metodą instancji "verify" i możesz pominąć metodę "new" (initialize), jeśli nic nie robi. Zwykle jest to najlepsza praktyka, dzięki czemu można korzystać z obiektów pierwszej klasy/zwykłych obiektów z rubinem. (Niektórzy mogą używać klasy z metodami klasowymi, które mają swoje "własne plusy i minusy"). Ponieważ ta klasa jest zależna od modelu Twojej firmy, powinieneś umieścić ją gdzieś w folderze aplikacji "aplikacja/usługi". Można tam umieścić małe pojedyncze klasy odpowiedzialności, które zawierają metodę lub dwie i są niezależne od warstwy internetowej. – jurglic

+0

Możesz także sprawdzić code_climate wpis na blogu, który opisuje podobny refactoring - wyodrębnianie kodu logicznego do nowej klasy z jedną odpowiedzialnością, napisanie prostej specyfikacji, a następnie użycie go jako PORO (zwykły-stary-ruby-obiekt) w kodzie ... : http://blog.codeclimate.com/blog/2013/07/23/testing-code-in-a-ils-initializer/ – jurglic

1

Jeśli testujesz kontroler, można uzyskać dostęp do kontrolera bezpośrednio:

controller.stub(:message) { 'this is the value to return' } 
+0

Ta odpowiedź działa dla mnie, ponieważ gdy używam metody, wiem, że wymaga ona argumentu, ale nie wiem, co to jest argument. Po prostu chcę przekazać argument wzdłuż, więc używam bloku z argumentem, aby zastąpić (stub) metodę. – Volte

Powiązane problemy