5 votes

test has_many avec validation en utilisant RSpc 2.9.0 + FactoryGirl 3.2

Nouveau pour RSpec et Factory Girl, et je perds cette bataille !

J'ai une table de jointure MealItems qui a une validation sur une de ses propriétés. Dans la console de rails, je peux faire ce qui suit avec succès :

meal = Meal.create!( ... )
food = Food.create!( ... )
item1 = MealItem.create!( meal, food, 1234 )  # 1234 being the property that is required

Je peux alors obtenir automatiquement un tableau d'aliments dans un repas donné à travers le MealItem comme ceci :

meal.foods

Le problème est que je n'arrive pas à comprendre comment créer correctement des usines pour que cette relation soit disponible dans la spécification. Je peux assigner les éléments à un repas et les tester, mais je n'arrive pas à faire fonctionner la relation has_many through (meal.foods).

Modèles

class Meal < ActiveRecord::Base

  has_many :meal_items
  has_many :foods, :through => :meal_items

end

class MealItem < ActiveRecord::Base

  belongs_to :meal
  belongs_to :food

  validates_numericality_of :serving_size, :presence => true,
                                           :greater_than => 0
end

class Food < ActiveRecord::Base

  has_many :meal_items
  has_many :meals, :through => :meal_items

end

spec/factories.rb

FactoryGirl.define do

  factory :lunch, class: Meal do
    name      "Lunch"
    eaten_at  Time.now
  end

  factory :chicken, class: Food do
    name            "Western Family Bonless Chicken Breast"
    serving_size    100
    calories        100
    fat             2.5
    carbohydrates   0
    protein         19
  end

  factory :cheese, class: Food do
     name            "Armstrong Light Cheddar"
     serving_size    30
     calories        90
     fat             6
     carbohydrates   0
     protein         8
   end

 factory :bread, class: Food do
    name            "'The Big 16' Multigrain Bread"
    serving_size    38
    calories        100
    fat             1
    carbohydrates   17
    protein         6
  end

  factory :item1, class: MealItem do
    serving_size      100
    association       :meal, factory: :lunch
    association       :food, factory: :chicken
  end

  factory :item2, class: MealItem do
      serving_size      15
      association       :meal, factory: :lunch
      association       :food, factory: :cheese
  end

  factory :item3, class: MealItem do
    serving_size      76
    association       :food, factory: :bread
    association       :meal, factory: :lunch
  end    

  factory :meal_with_foods, :parent => :lunch do |lunch|
    lunch.meal_items { |food| [ food.association(:item1),
                           food.association(:item2),
                           food.association(:item3)
                          ]}

  end
end

spec/models/meal_spec.rb

...

describe "Nutritional Information" do

before(:each) do 

  #@lunch = FactoryGirl.create(:meal_with_foods)  

  @item1 = FactoryGirl.create(:item1)
  @item2 = FactoryGirl.create(:item2)
  @item3 = FactoryGirl.create(:item3)
  @meal = FactoryGirl.create(:lunch)

  @meal.meal_items << @item1
  @meal.meal_items << @item2
  @meal.meal_items << @item3

  @total_cals = BigDecimal('345')
  @total_fat = BigDecimal('7.5')
  @total_carbs = BigDecimal('34')
  @total_protein = BigDecimal('35')

end

# Would really like to have
#it "should have the right foods through meal_items" do
  #@meal.foods[0].should == @item1.food
#end

it "should have the right foods through meal_items" do
  @meal.meal_items[0].food.should == @item1.food
end

it "should have the right amount of calories" do
  @meal.calories.should == @total_cals
end

...

Ma question est la suivante :

Comment dois-je configurer ces usines pour pouvoir référencer Meal.foods dans mes tests, car je ne peux pas attribuer des aliments directement à un repas en raison de l'exigence de validation de la table de jointure. Est-ce que je n'écris pas correctement les usines MealItem dans la base de données pendant le test, et c'est pourquoi la relation has_many through n'existe pas dans ma spécification ?

Toute aide est la bienvenue.

0voto

sockmonk Points 2257

Oui, vous avez besoin d'une fabrique pour MealItem, et vous devez utiliser cette fabrique dans la spécification afin de passer la validation. Si vous n'aviez pas d'autres champs obligatoires que les deux clés étrangères, cela fonctionnerait probablement déjà. Ainsi, après avoir configuré la fabrique avec une taille de serveur par défaut, vous remplaceriez ceci :

@meal.meal_items << @item1
@meal.meal_items << @item2
@meal.meal_items << @item3

avec ceci :

FactoryGirl.create(:meal_item, :meal => @meal, :item => @item1)
FactoryGirl.create(:meal_item, :meal => @meal, :item => @item1)
FactoryGirl.create(:meal_item, :meal => @meal, :item => @item1)

Une autre solution consisterait à définir une taille de portion par défaut dans votre modèle. Cela vous permettrait de laisser vos tests en l'état et faciliterait l'utilisation de votre syntaxe préférée dans votre code réel.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X