Rails mock_model, возвращающий TrueClass? - PullRequest
0 голосов
/ 24 октября 2010

Попытка проверить контроллер в Rspec. (Rails 2.3.8, Ruby 1.8.7, Rspec 1.3.1, Rspec-Rails 1.3.3)

Я пытаюсь опубликовать создание, но получаю сообщение об ошибке:

ActiveRecord :: AssociationTypeMismatch в «ProjectsController с соответствующими параметрами при входе в систему: следует создать проект» Ожидается пользователь (# 2171994580), получил TrueClass (# 2148251900)

Мой тестовый код выглядит следующим образом:

def mock_user(stubs = {})
  @user = mock_model(User, stubs)
end

def mock_project(stubs = {})
  @project = mock_model(Project, stubs)
end

def mock_lifecycletype(stubs = {})
  @lifecycletype = mock_model(Lifecycletype, stubs)
end

it "should create project" do
  post :create, :project => { :name => "Mock Project", 
    :description => "Mock Description",
    :owner => @user,
    :lifecycletype => mock_lifecycletype({ :name => "Mock Lifecycle" }) }
  assigns[:project].should == mock_project({ :name => "Mock Project",
    :description => "Mock Description",
    :owner => mock_user,
    :lifecycletype => mock_lifecycletype({ :name => "Mock Lifecycle" })})
  flash[:notice].should == "Project was successfully created."
end

Проблема возникает, когда я пытаюсь сделать :owner => @user в коде выше. По какой-то причине он думает, что мой @user TrueClass вместо User объекта класса. Забавно, что, если я закомментирую код post :create, и я сделаю простой @user.class.should == User, это сработает, а это означает, что @user действительно является объектом класса User.

Я тоже пробовал

:owner => mock_user
:owner => mock_user({ :name => "User",
  :email => "user@email.com",
  :password => "password",
  :password_confirmation => "password })
:owner => @current_user

Примечание. @Current_user также считается пользователем, который я тестировал (таким же образом, @current_user.class.should == User), а также возвращает TrueClass, когда я пытаюсь установить: owner.

Кто-нибудь знает, почему это происходит?

Спасибо!

1 Ответ

1 голос
/ 24 октября 2010

Из того, что я вижу, вы не создаете переменную вашего экземпляра, @user, прежде чем ссылаться на нее в операторе post. Хорошо бы создать переменные экземпляра до публикации, чтобы предварительные условия были сразу очевидны. Таким образом, вы можете узнать, был ли установлен @user.

Я знаю, что некоторые люди предпочитают метод написания таких строк, как «одна строка кода лучше, потому что я умный», но я обнаружил, что быть явным и даже повторяющимся - это действительно хорошая идея особенно в тестах.

Я добавляю следующий код, который, как я считаю, может лучше выразить ваши намерения, чем у вас. В моем коде я использую фиктивные ожидания, чтобы «ожидать», что Project создается с определенным набором параметров. Я полагаю, что ваш код предполагает, что вы можете сделать сравнение равенства между вновь созданным фиктивным проектом и другим, созданным во время выполнения вашего контроллера. Это может быть неправдой, потому что это совершенно разные объекты.

В моем коде, если у вас есть проблема с чем-то, оценивающим TrueClass или тому подобное, вы можете использовать строку кода, такую ​​как user.should be_a(User) в примере, чтобы убедиться, что все подключено правильно.

def mock_user(stubs = {})
  mock_model(User, stubs)
end

def mock_project(stubs = {})
  mock_model(Project, stubs)
end

def mock_lifecycletype(stubs = {})
  mock_model(Lifecycletype, stubs)
end

it "should create project" do
  user = mock_user
  owner = user
  lifecycletype = mock_lifecycletype({ :name => "Mock Lifecycle" })

  # Not certain what your params to create are, but the argument to with
  # is what the params are expected to be
  Project.should_receive(:create).once.with({:user => user, :owner => owner, :lifecycletype => lifecycletype})

  post :create, :project => { :name => "Mock Project", 
    :description => "Mock Description",
    :owner => @user,
    :lifecycletype => lifecycletype }
  flash[:notice].should == "Project was successfully created."
end
...