Test Post Controller con Rspec en Ruby

llevo poco tiempo investigando con Ruby on Rails y tengo una duda respecto a cómo debería testear correctamente mi Controller utilizando Rspec en.
Empecé la casa por el tejado, dejando el test para el final, y aunque en la comunicación entre el frontend y la api responde correctamente con un status:201 cuando todo va bien, en el test me devuelve un status:200.

este es mi User_Post_Controller:

  # POST /user   def create     begin       userName = params[:name]       CreateUserService.saveUser(userName)       json_response(userName, 201)       rescue Errors::UserExist       e = Errors::UserExist.new       json_response(e.message, e.status)     end       end 

El Routes.rb:

  post 'user', controller: :user_post, action: :create 

Y este es el Test que estaba diseñando:

require 'spec_helper' require 'rails_helper' require './app/controllers/user_post_controller' RSpec.describe UserPostController, type: :request do   describe "Create User" do     it "return status 201 when user is created" do       post "/user", params: {name: 'user'}       expect(response.status).to eq(201)     end   end end 

Dejo también por aquí la traza que me devuelve el test por consola:

 Failure/Error: expect(response.status).to eq(201)     expected: 201         got: 200     (compared using ==)  # ./spec/controllers/user_post_controller_spec.rb:10:in `block (3 levels) in <top (required)>' 

¿Cómo es posible que esté devolviendo un {status: 200} ?

Un saludo y gracias!

Qual o teste RSpec derivado a partir de um cenário e passo cucumber?

Cenário cucumber:

Funcionalidade: listar todos os usuarios do sistema Como Administrador do Sistema eu quero ver uma lista de todos os usuários do sistema  Contexto:     Dado que eu sou administrador do sistema com email "admin@admin.com" senha "admin123"     E que eu esteja na pagina backoffice  Esquema do Cenário: Listar todos os usuários     E que exista um usuário com nome "<username>", curso "<course>", email "<email>", registro "<registration>"     Quando eu clicar no link "Todos os usuários"     Então eu devo ver uma tabela com os dados:         | username     | <username>     |         | course       | <course>       |         | email        | <email>        |         | registration | <registration> |      Exemplos:         | username | course                 | email             | registration |         | João     | Ciência da Computação  | joao@gmail.com    | teste        |         | Genesio  | Engenharia de Software | genesio@gmail.com | 123123123    | 

Passo Cucumber:

Dado("que eu seja admin do sistema com email {string} e senha {string}") do |string, string2|     User.create(username: 'admin', email: string, password: string2,               registration: "15015296", course: "CIC", is_admin: true               )     visit new_user_session_path     fill_in :user_email, with: string     fill_in :user_password, with: string2     click_button "Log in" end  E("que eu esteja na pagina backoffice") do     visit(backoffice_path) end  Então("eu devo ver uma tabela com os dados:") do |table|     table.rows_hash.each do |field, value|         expect(page).to have_content(value)     end end  Então("eu devo estar em uma página com uma lista contendo o usuario       {string}, email {string}, curso {string}, e registro {string}")       do |string1 ,string2, string3, string4|      expect(page).to have_content(string1)      expect(page).to have_content(string2)      expect(page).to have_content(string3)      expect(page).to have_content(string4) end 

Preciso de uma tradução vamos dizer assim pra um teste RSpec, somente uma idéia de como ficaria o RSpec.

Adding RSpec coverage for a method with if/else logic

So I am fairly new to RSpec and Rails and I’ve been trying to learn RSpec as much as possible and I am really struggling with implementing coverage for methods that contain logic in them.

The app that I am practicing with uses coverage percentages to make sure I am properly covering the code I am implementing and I am missing coverage on the following method:

def initialize_business   businesses.each do |business|     if business.type == 'Restaurant'       @business_type = Business::Restaurant.new(json_directory: 'restaurant.json')     elsif business.type = 'Bar'       @business_type = Business::Bar.new(json_directory: 'bar.json')     else       @business_type = Business::Other.new(json_directory: 'other_business.json')     end   end   business_type = @business_type   initialize_business_creator(business_type) end 

My initial attempt at providing coverage (left out the other unrelated specs) but I struggled to even implement any coverage as I’m too new to RSpec:

describe '#initialize_business' do     subject do       described_class.new([business], business_sample_file).       initialize_business_creator     end      it 'assigns a value to @business_type' do       expect(assigns(@business_type)).to_not be_nil     end   end end 

I’m just looking for some help and/or guidance on how to implement specs for a method like this and I appreciate any and all help. Thank you!

How to rspec AbstractController methods?

I have two users, admin and local, i have assign update and delete method access to admin user only. Now i am trying to rspec my methods od active admin.

controller

def action_methods       if current_admin_user.admin?         super       elsif current_admin_user.local?         super - ['edit', 'destroy']       else         super       end     end 

Rspec

it "should not allow agency admin to delete global tag" do       @user.add_as_admin_of(@agency)       delete admin_tag_path(@tag)       expect(response).to have_http_status(404)#anything as per our requirment this is for show sample. end 

rspec is passing for admin as they can access all the CRUD operation, where as on local user it throws `Failure/Error: delete admin_tag_path(@tag)

 AbstractController::ActionNotFound:    AbstractController::ActionNotFound` 

which is correct because it can’t access those method but how can i Test them in rails.

The best way to test model methods in rails using rspec

I have one model class as listed here:

class Post < ActiveRecord::Base   has_many :comments    def tags     comments.map(&:tag).uniq.sort   end end 

and below is the best rspec as per my understanding:

 context 'tags' do let(:post) { Post.find_by_code('TX') }  it 'returns sorted alphabetically list of available tags' do   expect(post.tags).to eq(post.comments.map(&:tag).uniq.sort) end 

end

Do we any better way to test it or even it is nor require to test.

Test after_create_commit callback using `shoulda-callback-matchers` gem + rails 5 + rspec

I’m using shoulda-callback-matchers gem to test the callback. rails version is 5.2.2 and rspec version is 3.8.0.

Anyone know how to test after_create_commit callback using shoulda-callback-matchers gem ? It is working for after_create and after_update.

sample example context “callbacks” do let(:admission) { create(:admission) } it { expect(admission).to callback(:admission_created_notification).after(:create) } it { expect(admission).to callback(:admission_status_change_notification).after(:update) } end

thanks

Rspec validation project

I have created an open source project that uses Rspec to validate the formatting of AWS::CloudFormation::Init in CloudFormation templates.

My project is here.

Some general concerns:

  • Is this a valid use-case for using Rspec?

  • Is the documentation in the code okay?

I have some specific concerns about the code. Concerning the recursive compare() method:

# Method: compare # # Recursively compare real blocks in a CloudFormation template # with the spec defined in $  types. # # @param data [Hash] The real data in the template. # @param spec [Hash] The reference data corresponding to this #                    key in $  types. # def compare(data, spec)   if spec.is_a?(Hash)     check_keys(data.keys, spec.keys)   end   data.each do |k,v|     context k do       if spec == Array         it "#{k} should match Array" do           expect(v.class).to eq Array         end        elsif spec[k] == Hash         it "#{k} should match Hash" do           expect(v.class).to eq Hash         end        elsif spec == {String => Array} or             spec == {String => String}         it "#{k}=>#{v} should match #{spec}" do           expect(k.class).to eq spec.keys.first           expect(v.class).to eq spec[spec.keys.first]         end        elsif spec.has_key?(k)         if v.is_a?(Hash)           compare(v, spec[k]) # recurse.         else           spec_key = spec.keys.first           if spec_key.is_a?(Regexp)             it "#{k} should match #{spec_key}" do               expect(k).to match spec_key             end           elsif spec_key.is_a?(String)             it "#{k} should match #{spec_key}" do               expect(k.class).to eq String             end           elsif [Array, String,                  Fixnum, TrueClass,                  FalseClass].include?(v.class)             it "#{v} should be a #{spec[k]}" do               expect(v.class).to be_a spec[k]             end           end         end        elsif v.is_a?(Hash)         spec_key = spec.keys.first         compare(v, spec[spec_key]) # recurse.        else         raise "Something went wrong"       end     end   end end 
  • Can this conditional logic be simplified in any way?

The compare() method compares input data against this reference spec:

# This hash defines the expected format of # config sets in AWS::CloudFormation::Init blocks. # # Data types and regular expressions used as # placeholders for real values. # # Based on documentation here: # # https://docs.aws.amazon.com/AWSCloudFormation/ #   latest/UserGuide/aws-resource-init.html # $  types = {   'packages' => {     'apt'      => {String => Array},     'msi'      => {String => String},     'python'   => {String => Array},     'rpm'      => {String => String},     'rubygems' => {String => Array},     'yum'      => {String => Array},   },   'groups' => {     String => {'gid' => Fixnum},   },   'users' => {     String => {       'groups'  => Array,       'uid'     => Fixnum,       'homeDir' => String,     },   },   'sources' => {String => String},   'files' => {     String => {       'content'   => String,       'source'    => /^http/,       'encoding'  => /plain|base64/,       'group'     => String,       'owner'     => String,       'mode'      => Fixnum,       'authentication' => String,       'context'        => String,     },   },   'commands' => {     String => {       'command'  => String, # TODO. Apparently the only mandatory       'env'      => Hash,   #       attribute.       'cwd'      => String,       'test'     => String,       'ignoreErrors'   => Boolean,       'waitAfterCompletion' => Boolean,     },   },   'services' => {     /sysvinit|windows/ => {       String => {         'ensureRunning' => Boolean,         'enabled'   => Boolean,         'files'     => Array,         'sources'   => Array,         'packages'  => Array,         'commands'  => Array,       },     },   }, } 
  • Is the use of a global variable okay there? I chose that just to make it stand out.