RSpec没有路由匹配且文件不存在

时间:2018-03-12 16:39:24

标签: ruby-on-rails rest rspec routes nested

我使用this tutorial为我的Rails 5应用生成API。 这是在Comments和Post表之间。 帖子与评论的关系为1:m。

但是rspec每次测试都失败了。我一遍又一遍地检查了我的文件和层次结构,仍然没有看到问题所在。 以下是//JSON response [{ "data": [{ "Title": "asde", "abc": "asd23e", "Material": "asdf", "Quantity Jan2016 - Dec2016": 12576, "Sales Jan2016 - Dec2016": 1 }, { "Title": "asde", "abc": "345fs", "Material": "dsfvd 3343", "Quantity Jan2016 - Dec2016": 16560, "Sales Jan2016 - Dec2016": 6 }, { "Title": "asde", "abc": "7687", "Material": "af asdf", "Quantity Jan2016 - Dec2016": 12216, "Sales Jan2016 - Dec2016": 1 }], "totalPayloadSize": 539, // Total no. of entries "pageFrom": 0, // 1st entry "pageTo": 49, // 50th entry "pageSize": 50, // no. of entries to be shown "pageNo": 1, // 1st page, Pagination "monthsIn": [{ "fMonth": 1, "fYear": 2016, "tMonth": 12, "tYear": 2016 }] }]的输出:

rails routes

我的Prefix Verb URI Pattern Controller#Action post_comments GET /posts/:post_id/comments(.:format) comments#index POST /posts/:post_id/comments(.:format) comments#create post_comment GET /posts/:post_id/comments/:id(.:format) comments#show PATCH /posts/:post_id/comments/:id(.:format) comments#update PUT /posts/:post_id/comments/:id(.:format) comments#update DELETE /posts/:post_id/comments/:id(.:format) comments#destroy post_like POST /posts/:post_id/like(.:format) posts#like post_dislike POST /posts/:post_id/dislike(.:format) posts#dislike posts GET /posts(.:format) posts#index POST /posts(.:format) posts#create post GET /posts/:id(.:format) posts#show PATCH /posts/:id(.:format) posts#update PUT /posts/:id(.:format) posts#update DELETE /posts/:id(.:format) posts#destroy

config/routes.rb

Rails.application.routes.draw do resources :posts do resources :comments post :like post :dislike end end :(即使使用ActionController :: API,它也不起作用)

application_controller.rb

我的class ApplicationController < ActionController::Base include Response include ExceptionHandler protect_from_forgery with: :exception end

comments_controller.rb

最后,class CommentsController < ApplicationController before_action :set_post before_action :set_post_comment, only: [:show, :update, :destroy] # GET /comments # GET /comments.json def index #@comments = Comment.all json_response(@post.comments) end # GET /comments/1 # GET /comments/1.json def show json_response(@comment) end # POST /comments # POST /comments.json def create @comment = Comment.new(comment_params) @post.comments.create!(comment_params) json_response(@post, :created) if @comment.save render :show, status: :created, location: @comment else render json: @comment.errors, status: :unprocessable_entity end end private # Use callbacks to share common setup or constraints between actions. def set_comment @comment = Comment.find(params[:id]) end # Never trust parameters from the scary internet, only allow the white list through. def comment_params params.require(:comment).permit(:commenter, :comment, :description, :post) end def set_post @post = Post.find(params[:post_id]) end def set_post_comment @comment = @post.comments.find_by!(id: params[:id]) if @post end end

posts_controller.rb

更新:显示规范文件 我的class PostsController < ApplicationController before_action :set_post, only: [:show, :update, :destroy] # GET /posts # GET /posts.json def index @posts = Post.all json_response(@posts) end # GET /posts/1 # GET /posts/1.json def show json_response(@post) end # POST /posts # POST /posts.json def create @post = Post.new(post_params) json_response(@post, :created) if @post.save render :show, status: :created, location: @post else render json: @post.errors, status: :unprocessable_entity end end private # Use callbacks to share common setup or constraints between actions. def set_post @post = Post.find(params[:id]) end # Never trust parameters from the scary internet, only allow the white list through. def post_params params.require(:post).permit(:poster, :vote, :description, :comment, :user_id, :image_base) end end

spec/requests/comments_spec.rb

require 'rails_helper' RSpec.describe "Comments", type: :request do # Initialize the test data let!(:post) { create(:post) } let!(:comments) { create_list(:comment, 20, post_id: post.id) } let(:post_id) { post.id } let(:id) { comments.first.id } # Test suite for GET /posts/:post_id/comments describe 'GET /posts/:post_id/comments' do before { get "/posts/#{post_id}/comments" } context 'when post exists' do it 'returns status code 200' do expect(response).to have_http_status(200) end it 'returns all post comments' do expect(json.size).to eq(20) end end context 'when post does not exist' do let(:post_id) { 0 } it 'returns status code 404' do expect(response).to have_http_status(404) end it 'returns a not found message' do expect(response.body).to match(/Couldn't find Post/) end end end # Test suite for GET /posts/:post_id/comments/:id describe 'GET /posts/:post_id/comments/:id' do before { get "/posts/#{post_id}/comments/#{id}" } context 'when post item exists' do it 'returns status code 200' do expect(response).to have_http_status(200) end it 'returns the item' do expect(json['id']).to eq(id) end end context 'when post item does not exist' do let(:id) { 0 } it 'returns status code 404' do expect(response).to have_http_status(404) end it 'returns a not found message' do expect(response.body).to match(/Couldn't find Comment/) end end end # Test suite for PUT /posts/:post_id/comments describe 'POST /posts/:post_id/comments' do let(:valid_attributes) { { comment: 'A Comment', commenter: 'Luke Shaw' } } context 'when request attributes are valid' do before { post "/posts/#{post_id}/comments", params: valid_attributes } it 'returns status code 201' do expect(response).to have_http_status(201) end end context 'when an invalid request' do before { post "/posts/#{post_id}/comments", params: {} } it 'returns status code 422' do expect(response).to have_http_status(422) end it 'returns a failure message' do expect(response.body).to match(/Validation failed: Commenter or Comment can't be blank/) end end end end

spec/requests/posts_spec.rb

require 'rails_helper' RSpec.describe "Posts", type: :request do # initialize test data let!(:posts) { create_list(:post, 10) } let(:post_id) { posts.first.id } describe "GET /posts" do # make HTTP get request before each example before { get '/posts' } it 'returns posts' do # Note `json` is a custom helper to parse JSON responses expect(json).not_to be_empty expect(json.size).to eq(10) end it 'returns status code 200' do expect(response).to have_http_status(200) end end # Test suite for GET /posts/:id describe 'GET /posts/:id' do before { get "/posts/#{post_id}" } context 'when the record exists' do it 'returns the post' do expect(json).not_to be_empty expect(json['id']).to eq(post_id) end it 'returns status code 200' do expect(response).to have_http_status(200) end end context 'when the record does not exist' do let(:post_id) { 100 } it 'returns status code 404' do expect(response).to have_http_status(404) end it 'returns a not found message' do expect(response.body).to match(/Couldn't find Post/) end end end

spec/models/post_spec.rb

ANd require 'rails_helper' RSpec.describe Post, type: :model do # Association test # ensure Post model has a 1:m relationship with the Comment model it { should have_many(:comments).dependent(:destroy) } # Validation tests # ensure columns are present before saving it { should validate_presence_of(:poster) } it { should validate_presence_of(:description) } end

spec/models/comment_spec.rb

更新2:显示spec / factories / * .rb文件 显示require 'rails_helper' RSpec.describe Comment, type: :model do # Association test # ensure a comment record belongs to a single post record it { should belong_to(:post) } # Validation test # ensure column name is present before saving it { should validate_presence_of(:comment) } it { should validate_presence_of(:commenter) } end

spec/factories/posts.rb

显示FactoryBot.define do factory :post do image { Rack::Test::UploadedFile.new(Rails.root.join('public', 'system', 'posts', 'images', '000', '000', '001', 'original', 'img1.jpeg'), 'image/jpeg') } poster { Faker::Lorem.sentence } vote { Faker::Number.number(10).to_i} description { Faker::Lorem.paragraph } end end

spec/factories/comments.rb

我的`路由显示明确的继承,我在我的控制器中强制执行。不过,我得到的错误如下:

  

失败/错误:期待(:delete =&gt;&#34; / comments / 1&#34;)。to route_to(&#34; comments#destroy&#34;,:id =&gt;&#34; 1&#34)           没有路线匹配&#34; / comments / 1&#34;   和   RuntimeError:          /home/user/projects/app/public/system/posts/images/000/000/001/original/img1.jpeg文件不存在

1 个答案:

答案 0 :(得分:1)

好的,导致每个规范失败的错误是上传的图像。它无法找到您尝试上传的图像文件。该图像文件实际位于何处?创建该文件并将其放在正确的位置,它们应该重新开始工作。

至于路由规范 - 这是您在问题中包含的错误,并且它只会根据您的粘贴垃圾箱本地化为您的路由规范(spec/routing/comments_routing_spec.rb ),只需将路线调整为嵌套路线即可修复。它们应该包括使路线工作所需的一切(包括有效的后id)。

其次,它应该是这样的:

expect(:delete => "/posts/1/comments/1").to route_to("comments#destroy", :id => "1", :post_id => "1")

注意:就我个人而言,我不会为简单资源而烦恼,只是为了复杂的资源,但是当你习惯使用Rails时,你可能更喜欢它作为备份。