jpywtora at calpoly.edu
2006-Dec-19 08:39 UTC
[mocha-developer] Stubbing ActiveRecord Models gets very difficult with instance methods
I have seen some basic examples of using Mocha and Stubba with ActiveRecord Models; However, the ones I read were somewhat simplistic. That is they stubbed the find class method of the model, or the execute method of the connection object. While stubbing the find method had the desired effect for the author it did not help with a situation I was hacking away on. Which was writing a test case for an instance method of a model. I wanted to eliminate the database connection and select_all calls with stubs in my test methods. Thus, my class finders would return real AR objects. Stubbing the find method obviously makes the class method return objects that are close enough; However, to test instance methods for your model you need real ActiveRecord objects. You can make stubs for all the attributes, but the instance methods under test need to be there. This is the problem I could not overcome, at least in today''s hacking attempts. Another ActiveRecord hickup is the trip the it makes to the database to discover the Model attributes, so do you allow that to still occur? Do it in the setup of your test case? I suppose one could put these important methods in a module and mix them in to the model, but this seems slightly off as a comprise for testing sake. Any thoughts anyone? Maybe this is not the right place for Mocha and Stubba? Maybe this is just the type of thing a real test database and test cases are the best solution. Something like the Rails fixture approach. I was able to solve my specific case by making my instance method a class method, which turned out to be a better fit; However, it left me wondering and that is why I ask. Thanks http://ruby-talk.blogspot.com
James Mead
2006-Dec-19 12:45 UTC
[mocha-developer] Stubbing ActiveRecord Models gets very difficult with instance methods
Stubbing attributes sounds like a bad idea. Turning instance methods into class methods for testing sounds like a bad idea. We do choose to allow the database trip to determine model attributes. In my opinion, it''s not worth mocking this out. Can you give a concrete example of an instance method you are having problems testing? Examples are much easier to discuss without ambiguity. -- James. http://blog.floehopper.org
John Pywtorak
2007-Jan-03 19:02 UTC
[mocha-developer] Stubbing ActiveRecord Models gets very difficult with instance methods
James Mead wrote:> Stubbing attributes sounds like a bad idea. > Turning instance methods into class methods for testing sounds like a bad idea. > > We do choose to allow the database trip to determine model attributes. > In my opinion, it''s not worth mocking this out. > > Can you give a concrete example of an instance method you are having > problems testing? Examples are much easier to discuss without > ambiguity. >I couldn''t agree more. And, here is an example. module Fear module Models class StatsTb < ActiveRecord::Base set_table_name "w.stats_tb" def check_stat h, m = maint_time.split(":").map(&:to_i) m_dt = maint_dt.to_time + m.hours + m.minutes now = Time.now m_dt.day == now.day && now - m_dt > 0 end def self.find_stats stats = [] %w(P_TB P_CURRENT_FLAGS_TB X_TB).each do |tb| stats << StatsTb.find_by_table_name( tb, :order => "maint_dt desc nulls last", :readonly => true ) end stats end end end end This example is not meant to serve as a best solution, or even a good solution. It is only for demonstrating difficulty of stubbing for ActiveRecord model instance methods testing. So, you can see from the model we have a table with maint_time, maint_dt, and table_name columns. StatsTb#check_stat is attempting to verify a given instance of StatsTb. So, how would one go about writing a test for check_stat, specifically using mocha? Also, attempting to eliminate all trips to the database, because testing #check_stat does not need it. The db connection and all the active record magic are tested elsewhere right? So, here was a first attempt example: require ''test/unit'' require ''date'' require ''fear'' class ModelsTest < Test::Unit::TestCase attr :stat def setup @stat = stub(:table_name => "P_TB", :maint_dt => Date.today, :maint_time => "00:00") end def test_check StatsTb.stubs(:find_by_table_name).returns(stat) StatsTb.find_stats.each { |st| assert st.check } end end So, this does not work, because the blocks st object is not an instance a real instance with a check method and I can''t stub check, because it is the method under test. Thanks James for any advice and suggestions.
John Pywtorak
2007-Jan-03 21:48 UTC
[mocha-developer] Stubbing ActiveRecord Models gets very difficult with instance methods
Second try with minor correction, doh! James Mead wrote:> Stubbing attributes sounds like a bad idea. > Turning instance methods into class methods for testing sounds like a bad idea. > > We do choose to allow the database trip to determine model attributes. > In my opinion, it''s not worth mocking this out. > > Can you give a concrete example of an instance method you are having > problems testing? Examples are much easier to discuss without > ambiguity.I couldn''t agree more. And, here is an example. module Fear module Models class StatsTb < ActiveRecord::Base set_table_name "w.stats_tb" def check_stat h, m = maint_time.split(":").map(&:to_i) m_dt = maint_dt.to_time + m.hours + m.minutes now = Time.now m_dt.day == now.day && now - m_dt > 0 end def self.find_stats stats = [] %w(P_TB P_CURRENT_FLAGS_TB X_TB).each do |tb| stats << StatsTb.find_by_table_name(tb, :order => "maint_dt desc nulls last", :readonly => true) end stats end end end end This example is not meant to serve as a best solution, or even a good solution. It is only for demonstrating difficulty of stubbing for ActiveRecord model instance methods testing. So, you can see from the model we have a table with maint_time, maint_dt, and table_name columns. StatsTb#check_stat is attempting to verify a given instance of StatsTb. So, how would one go about writing a test for check_stat, specifically using mocha? Also, attempting to eliminate all trips to the database, because testing #check_stat does not need it. The db connection and all the active record magic are tested elsewhere right? So, here was a first attempt example: require ''test/unit'' require ''date'' require ''fear'' class ModelsTest < Test::Unit::TestCase attr :stat def setup @stat = stub(:table_name => "P_TB", :maint_dt => Date.today, :maint_time => "00:00") end def test_check StatsTb.stubs(:find_by_table_name).returns(stat) StatsTb.find_stats.each { |st| assert st.check_stat } end end So, this does not work, because the blocks st object is not an instance a real instance with a check method and I can''t stub check, because it is the method under test. Thanks James for any advice and suggestions.
Francois Beausoleil
2007-Jan-04 14:51 UTC
[mocha-developer] Stubbing ActiveRecord Models gets very difficult with instance methods
Hello John, 2007/1/3, John Pywtorak <jpywtora at calpoly.edu>:> Second try with minor correction, doh! > require ''test/unit'' > require ''date'' > require ''fear'' > class ModelsTest < Test::Unit::TestCase > attr :stat > > def setup > @stat = stub(:table_name => "P_TB", :maint_dt => Date.today, > :maint_time => "00:00") > end > > def test_check > StatsTb.stubs(:find_by_table_name).returns(stat) > StatsTb.find_stats.each { |st| assert st.check_stat } > end > end > > So, this does not work, because the blocks st object is not an instance > a real instance with a check method and I can''t stub check, because it > is the method under test.What''s wrong with doing this: def test_check @stat = StatTb.new @stat.stubs(:maint_dt).returns(Date.today) @stat.stubs(:maint_time).returns("00:00") assert @stat.check_stat end Or even: def test_check @stat = StatTb.new(:maint_dt => Date.today, :maint_time => "00:00") assert @stat.check_stat end There is not even any need to stub anything in the second version. You''ll get one DB hit, to get the columns, but after that, it should be connection free. I hope I understood your problem correctly. Bye ! -- Fran?ois Beausoleil http://blog.teksol.info/ http://piston.rubyforge.org/
James Mead
2007-Jan-04 15:28 UTC
[mocha-developer] Stubbing ActiveRecord Models gets very difficult with instance methods
I agree with Francois. I think you are trying to test too much in your test. Francois has suggested tests which test only the check_stat method. You could also have a separate test for the find_stats method in which you could stub out the find_by_table_name method. Does that make sense? -- James. http://blog.floehopper.org -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/mocha-developer/attachments/20070104/a9135442/attachment.html
Jay
2007-Jan-04 18:23 UTC
[mocha-developer] Stubbing ActiveRecord Models gets very difficult with instance methods
On Jan 3, 2007, at 4:48 PM, John Pywtorak wrote:> So, how would one go about writing > a test for check_stat, specifically using mocha? Also, attempting to > eliminate all trips to the database, because testing #check_stat does > not need it. The db connection and all the active record magic are > tested elsewhere right?If you want to eliminate all trips to the database and unit test check_stat you can do this: http://jayfields.blogspot.com/2006/12/ rails-activerecord-unit-testing.html -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/mocha-developer/attachments/20070104/59e07f65/attachment.html
John Pywtorak
2007-Jan-05 03:05 UTC
[mocha-developer] Stubbing ActiveRecord Models gets very difficult with instance methods
Jay wrote:> On Jan 3, 2007, at 4:48 PM, John Pywtorak wrote: > >> So, how would one go about writing >> >> a test for check_stat, specifically using mocha? Also, attempting to >> >> eliminate all trips to the database, because testing #check_stat does >> >> not need it. The db connection and all the active record magic are >> >> tested elsewhere right? >> > > If you want to eliminate all trips to the database and unit test > check_stat you can do > this: http://jayfields.blogspot.com/2006/12/rails-activerecord-unit-testing.htmlThanks. I had looked sometime ago and very little had been blogged about, or other. For various reasons I had not stayed up on Jay''s blog, so wow, I am seeing my questions answered within his posts. Thank you Jay. http://ruby-talk.blogspot.com
John Pywtorak
2007-Jan-05 03:11 UTC
[mocha-developer] Stubbing ActiveRecord Models gets very difficult with instance methods
Francois Beausoleil wrote:> Hello John, > > 2007/1/3, John Pywtorak <jpywtora at calpoly.edu>: >> Second try with minor correction, doh! >> require ''test/unit'' >> require ''date'' >> require ''fear'' >> class ModelsTest < Test::Unit::TestCase >> attr :stat >> >> def setup >> @stat = stub(:table_name => "P_TB", :maint_dt => Date.today, >> :maint_time => "00:00") >> end >> >> def test_check >> StatsTb.stubs(:find_by_table_name).returns(stat) >> StatsTb.find_stats.each { |st| assert st.check_stat } >> end >> end >> >> So, this does not work, because the blocks st object is not an instance >> a real instance with a check method and I can''t stub check, because it >> is the method under test. > > What''s wrong with doing this: > > def test_check > @stat = StatTb.new > @stat.stubs(:maint_dt).returns(Date.today) > @stat.stubs(:maint_time).returns("00:00") > assert @stat.check_stat > end > > Or even: > > def test_check > @stat = StatTb.new(:maint_dt => Date.today, :maint_time => "00:00") > assert @stat.check_stat > end > > There is not even any need to stub anything in the second version. > You''ll get one DB hit, to get the columns, but after that, it should > be connection free. > > I hope I understood your problem correctly. > > Bye !Yes, thanks I think that can work. I had kind off locked myself into the dynamic magic nature of activerecord and wanted to avoid anything that newer versions of activerecord might break, or running into scaling issues as my example is very much a simple case. I see that Jay Fields blog about this in much detail, so I am off the read his posts. Thanks again. John http://ruby-talk.blogspot.com
John Pywtorak
2007-Jan-05 03:14 UTC
[mocha-developer] Stubbing ActiveRecord Models gets very difficult with instance methods
James Mead wrote:> I agree with Francois. I think you are trying to test too much in your test. > > Francois has suggested tests which test only the check_stat method. > > You could also have a separate test for the find_stats method in which > you could stub out the find_by_table_name method. > > Does that make sense? > -- > James. > http://blog.floehopper.org >Yes, I think I was testing to much and it makes sense. I look forward to the next release of mocha. John http://ruby-talk.blogspot.com
Seemingly Similar Threads
- Problems with Excel & MS Word files (still)
- [PATCH] Add command trace functionality
- [PATCH libguestfs] syntax-check: expand TABs in generator.ml
- [PATCH] generator: Fix API of functions that return RBufferOut
- [PATCH 1/2] gobject: Use generator_built macro to ensure generated files are rebuilt properly.