Тестирование создания связанных объектов при обратном вызове с помощью Rspec on Rails - PullRequest
3 голосов
/ 26 октября 2011

Попытка обернуть голову вокруг rspec и правильного тестирования, и у нас возникли трудности с выполнением следующих действий должным образом

Скажем, у нас есть три класса, например

Class User
    belongs_to :company
    has_and_belongs_to_many :roles
end

Class Company
    has_many :users
end

Class Role
    has_and_belongs_to_many :users
end

В классе User Iиметь обратный вызов before_create, который назначает роль по умолчанию «company_admin» пользователя, если пользователь первым связывается с компанией

def check_for_initial_company_admin_role
  if self.company.users.count == 0
    self.roles << Role.find_by_name("company_admin")
  end
end

Как правильно проверить в спецификации модели, что ему назначают 'роль company_admin в случае, если он первый пользователь, связанный с компанией?


ОБНОВЛЕНИЕ рабочее решение

describe "#check_for_initial_company_admin_role" do
  it "sets the first user created to be the administrator" do
    Factory(:role)
    user = Factory(:user)

    user.roles.count.should be > 0
    user.roles.should include Role.find_by_name("company_admin")
  end
end


Factory.define :user do |f|
  f.email { Factory.next(:email) }
  f.password "secret"
  f.password_confirmation "secret"
  f.association :company
end 

Factory.define :role do |f|
  f.name "company_admin"
end

Factory.define :company do |f|
  f.name "foobar"
  f.vat_id "1234"
end

Ответы [ 2 ]

1 голос
/ 26 октября 2011

Я бы подошел к этому так:

describe "#check_for_initial_company_admin_role" do
  it "sets the first user created to be the administrator" do
    company = Factory(:company)
    user = Factory(:user)
    company.users << user


    user.roles.count.should > 0
    user.roles.should include Role.find_by_name("company_admin")
  end
end

Здесь может быть неверное предположение, что вы используете Factory Girl в своей тестовой среде.Если нет, то это на самом деле не меняет «мясо» этого теста ... только те первые строки, где вы создаете компанию и пользователя.

Вы также можете при желании проверить пользователя со стороны компании.но, честно говоря, это похоже на совершенно другой тест - один тестирует связь между этими моделями.

Подход, который я выбрал бы, заключается в том, что, поскольку это на самом деле тест модели, вам нужно создавать и изменять объекты реальной модели,вместо того, чтобы издеваться над этими объектами.Если бы это был тест контроллера, я бы издевался над моделями и настойчиво заглушал модели.

Надеюсь, это поможет и поможет решить ваш вопрос.Если нет, дайте мне знать, где я нахожусь за пределами базы, и я сделаю еще один проход :) Я только около года на rspec, но я обнаружил, что, как только я обернулся, как тестировать модели противконтроллеры я полюбил это.

0 голосов
/ 26 октября 2011

Не изменяя существующую логику, я бы протестировал эту логику в user_spec следующим образом:

describe User do
  let!(:admin_role) { Role.create!(name: 'company_admin') }
  let!(:company) { Company.create! }

  it 'should be added to the default role when created' do
    user = company.users.create!(name: 'Joe', email: 'joe@email.com')

    user.should have(1).roles
    user.roles.first.should == admin_role
  end
end

Примечание. Я бы использовал что-то вроде FactoryGirl для роли администратора и объектов компании, чтобы сделать их многократно используемыми.

Использование вами имени роли для обозначения поведения не является идеальным. Скорее всего, это приведет к большому количеству разбросанной логики в вашем приложении, где вы найдете роль по ее имени и сверяете имя с помощью операторов if / else или case. Я бы рекомендовал использовать единственное наследование таблиц Rail и перенести всю логику роли администратора в отдельный класс. Это сохранит логику модели и облегчит тестирование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...