2016-12-22 2 views
0

Je n'arrive pas à faire un test pour le contrôleur de mon poste. Quelle est la bonne façon de tester mon action create dans le contrôleur Posts avec une association polymorphique?Comment tester une association polymorphe sur un contrôleur avec Minitest?

J'utilise Rails 4

Voici mon code

Modèles:

class Topic < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :category 
    has_many :posts, as: :postable 
    has_many :posts, dependent: :destroy 
    validates :name, presence: true, length: {maximum: 50} 
    validates :description, presence: true, length: {maximum: 80} 
    validates :user_id, presence: true 
    is_impressionable 
end 

class Post < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :topic 
    belongs_to :category 
    belongs_to :postable, polymorphic: true 
    has_many :posts, as: :postable 
    validates :comment, presence: true 
    validates :user_id, presence: true 
    validates :topic_id, presence: true 
    validates :category_id, presence: true 
    default_scope { order(created_at: :asc) } 
end 

contrôleur post

class PostsController < ApplicationController 
    before_action :auth_user 
    before_action :set_post, only: [:destroy] 
    before_action :correct_user, only: [:destroy] 
    before_action :find_postable, only: [:create, :new] 

    def new 
    @post = @postable.posts.build 
    end 

    def create 
    @post = @postable.posts.build(post_params) 
    set_topic_id 
    set_category_id 
    @post.user_id = current_user.id 
    if @post.save 
     redirect_to topic_path(@post.topic.id) 
    else 
     redirect_to request.referer, notice: "Post unsuccessful!" 
    end 
    end 

    def destroy 
    @post.destroy 
    flash[:success] = 'Post deleted' 
    redirect_to request.referer || root_url 
    end 

    private 

    def set_post 
    @post = Post.find(params[:id]) 
    end 

    def correct_user 
    @post = current_user.posts.find_by(id: params[:id]) 
    redirect_to root_url if @post.nil? 
    end 

    def find_topic 
    @topic = Topic.find(params[:topic_id]) 
    end 

    def find_postable 
    @postable = Post.find_by_id(params[:post_id]) if params[:post_id] 
    @postable = Topic.find_by_id(params[:topic_id]) if  
    params[:topic_id] 
    end 

    def post_params 
    params.require(:post).permit(:comment) 
    end 
end 

contrôleur post test:

require 'test_helper' 

class PostsControllerTest < ActionController::TestCase 

    def setup 
    @topic = topics(:topicone) 
    @post = posts(:postone) 
    @posttwo = posts(:posttwo) 
    @category = categories(:categoryone) 
    @user = users(:user1) 
    end 

    test 'should create post when logged in' do 
    sign_in @user 
    assert_difference 'Post.count', 1 do 
     post :create, post: { user_id: @user.id, category_id:  
     @category.id, topic_id: @topic.id, comment: "First reply!", 
     postable_id: @post.id, postable_type: "Post" } 
    end 
    end 
end 

Quand je lance le test ci-dessus je reçois cette erreur:

ERROR["test_should_create_post_when_logged_in", PostsControllerTest,  
    2016-12-04 14:23:25 -0500] 
    test_should_create_post_when_logged_in#PostsControllerTest 
    (1480879405.93s) 
NoMethodError: NoMethodError: undefined method `posts' for nil:NilClass 
     app/controllers/posts_controller.rb:13:in `create' 
     test/controllers/posts_controller_test.rb:28:in `block (2 
levels) in <class:PostsControllerTest>' 
     test/controllers/posts_controller_test.rb:25:in `block in 
<class:PostsControllerTest>' 
    app/controllers/posts_controller.rb:13:in `create' 
    test/controllers/posts_controller_test.rb:28:in `block (2 levels) 
in <class:PostsControllerTest>' 
    test/controllers/posts_controller_test.rb:25:in `block in 
<class:PostsControllerTest>' 

De ma compréhension, je crois qu'il me dit qu'il ne peut pas trouver si l'action create est annonce à un poste ou à un sujet. Le site fonctionne très bien dans le développement et la production. Le problème est dans ce test. Comment puis-je réécrire ce test et faire en sorte qu'il reconnaisse à qui il est posté?

Répondre

0

J'ai trouvé une solution à ce peu de temps après.

Dans ce cas, pour tester avec succès si un poste est créé sur un sujet, assurez-vous de fournir le topic_id.

test 'should create post on a topic when logged in' do 
    sign_in @user 
    assert_difference 'Post.count', 1 do 
    post :create, topic_id: @topic, post: { 
       user_id: @user.id, 
       category_id: @category.id, 
       comment: 'First post on a topic!' } 
    end 
end 

Maintenant, pour tester si un post est créé sur un autre message, assurez-vous de fournir le post_id.

test 'should create post on another post when logged in' do 
    sign_in @user 
    assert_difference 'Post.count', 1 do 
    post :create, post_id: @post, post: { 
       user_id: @user.id, 
       category_id: @category.id, 
       comment: 'First post on a topic!' } 
    end 
end