Ruby on rails 测试RubyonRails单元测试中是否调用了函数

Ruby on rails 测试RubyonRails单元测试中是否调用了函数,ruby-on-rails,unit-testing,Ruby On Rails,Unit Testing,我正在使用TestUnit,并想确定是否调用了函数。我在一个名为Person的类中有一个方法,我将其设置为“在更新之前”调用: def geocode_if_location_info_changed if location_info_changed? spawn do res = geocode end end end 然后我有一个单元测试: def test_geocode_if_location_info_changed p

我正在使用TestUnit,并想确定是否调用了函数。我在一个名为Person的类中有一个方法,我将其设置为“在更新之前”调用:

def geocode_if_location_info_changed
    if location_info_changed?
      spawn do
        res = geocode
      end
    end
  end
然后我有一个单元测试:

def test_geocode_if_location_info_changed
  p = create_test_person
  p.address = "11974 Thurloe Drive"
  p.city = "Baltimore"
  p.region = Region.find_by_name("Maryland")
  p.zip_code = "21093"
  lat1 = p.lat
  lng1 = p.lng

  # this should invoke the active record hook
  # after_update :geocode_if_location_info_changed
  p.save
  lat2 = p.lat
  lng2 = p.lng
  assert_not_nil lat2
  assert_not_nil lng2
  assert lat1 != lat2
  assert lng1 != lng2

  p.address = "4533 Falls Road"
  p.city = "Baltimore"
  p.region = Region.find_by_name("Maryland")
  p.zip_code = "21209"

  # this should invoke the active record hook
  # after_update :geocode_if_location_info_changed
  p.save

  lat3 = p.lat
  lng3 = p.lng
  assert_not_nil lat3
  assert_not_nil lng3
  assert lat2 != lat3
  assert lng2 != lng3
end
如何确保调用了“geocode”方法?对于我希望确保在位置信息未更改时不调用它的情况,这一点更为重要


谢谢

您需要的是模拟对象(有关更多一般信息,请参阅和)。RSpec有,而且还有其他独立的库(例如),如果您不需要切换到RSpec,这些库应该可以帮助您

用摩卡咖啡。这将测试过滤器的逻辑:

def test_spawn_if_loc_changed
  // set up omitted
  p.save!
  p.loc = new_value
  p.expects(:spawn).times(1)
  p.save!
end

def test_no_spawn_if_no_data_changed
  // set up omitted
  p.save!
  p.other_attribute = new_value
  p.expects(:spawn).times(0)
  p.save!
end

我应该在这里嘲笑什么?我的person对象是正在测试的系统,根据Martin Fowler的文章,mocks应该用于协作者。我同意这个答案,尽管我认为您希望
p.expects(:geocode\u if\u location\u info\u changed)。times(1)
。我可以在这里用摩卡咖啡。在我看来,before过滤器似乎与合作者非常接近。我试图测试before过滤器的逻辑,而spawn是if中的第一件事。如果您只是测试before过滤器的调用,那么您只是在测试“before_过滤器”是否存在以及rails是否正常工作。。。这很好,但我们似乎正在尝试获取过滤器中的逻辑。谢谢你的回答,但我想知道“地理代码”是否在spawn中被调用。不管怎样,当我执行p.expects(:spawn).times(1)时,当程序第一次生成时,它实际上会被跳过而不被调用吗?我猜另一个选项是执行类似Person.any_instance.stubs(:geocode).returns(true)的操作我可能会隔离这些行为,以确保一切正常:为了测试geocode是否在#spawn内部调用,如果#location_info_更改,您可以直接调用#geocode_:然后存根位置_info_更改?为true,并期望模拟地理代码。