Forum: RSpec How to test update_attribute with mocha?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
anmaxp (Guest)
on 2009-05-14 04:47
(Received via mailing list)
Hey everyone,

I'm having sort of an issue here, I'm trying to test the update of the
last_login field upon login, here is my test

  it "assigns a new last_login timestamp" do
    User.expects(:update_attribute).at_least_once.returns(true)
    post :create, :email => 'removed_email_address@domain.invalid', :password => 
'test'
 end

sessions_controller:

  def create

    self.current_user = current_account.users.authenticatex(params
[:email], params[:password], current_account)

    if logged_in?

      Time.zone = current_user.timezone
      I18n.locale = current_user.language

      login_flash(current_user)
      current_user.login_updates(current_account.id)

      redirect_back_or_default(default_path)

    else
      flash.now[:error] = t('flash.notice.invalidcredentials')
      render :action => 'new'
    end
  end

and the login updates_method on the user model:

  def login_updates(account)
    self.update_attribute(:last_login, Time.zone.now)
  end

no matter what variation of expects(:update), expects
(:update_attribute) I always get the same failed test:

#<Mock:0x53091e8>.update_attribute(any_parameters) - expected calls:
at least 1, actual calls: 0
Phlip (Guest)
on 2009-05-14 08:09
(Received via mailing list)
anmaxp wrote:

> I'm having sort of an issue here, I'm trying to test the update of the
> last_login field upon login, here is my test
>
>   it "assigns a new last_login timestamp" do
>     User.expects(:update_attribute).at_least_once.returns(true)

User.any_instance.expects(:update_attribute).with(:field, value).etc.

An instance of User will itself call the .update_attribute. The class
won't call it.

However, I can't think of a reason not to just write the record, reload
it, and
check the fields. And a _functional_ test should not care how the record
got
written (update_attribute, save, or whatever). A unit test might care,
but
functional tests need a little more float...

--
   Phlip
   http://flea.sourceforge.net/resume.html
Matt W. (Guest)
on 2009-05-14 10:55
(Received via mailing list)
On 14 May 2009, at 05:01, Phlip wrote:

> An instance of User will itself call the .update_attribute. The
> class won't call it.
>
> However, I can't think of a reason not to just write the record,
> reload it, and check the fields. And a _functional_ test should not
> care how the record got written (update_attribute, save, or
> whatever). A unit test might care, but functional tests need a
> little more float...

I've got a reason. You're coupling the tests for this simple little
controller class to all the infrastructure and dependencies needed to
write the record to the database and reload it again. As easy as Rails
makes it for us to manage our database schemas, gratuitously
introducing dependencies in your code like this is a bad habit to get
into. It can lead to tests that are fragile to failing when code is
changed far away from the place they're apparently testing. The tests
also run slowly, which makes working on systems written like this
boring.

I would argue that a true 'functional test'[1] would not even care
that there is a controller class, and would be exercising the system
via the user interface.

[1]http://c2.com/cgi/wiki?FunctionalTest

Matt W.
http://beta.songkick.com
http://blog.mattwynne.net
Phlip (Guest)
on 2009-05-14 17:30
(Received via mailing list)
Matt W. wrote:

> I've got a reason. You're coupling the tests for this simple little
> controller class to all the infrastructure and dependencies needed to
> write the record to the database and reload it again. As easy as Rails
> makes it for us to manage our database schemas, gratuitously introducing
> dependencies in your code like this is a bad habit to get into. It can
> lead to tests that are fragile to failing when code is changed far away
> from the place they're apparently testing. The tests also run slowly,
> which makes working on systems written like this boring.

The point of unit tests (which include the alleged "functional tests" in
Rails)
is to fail more often than production code would fail. Not less often.

--
   Phlip
   http://flea.sourceforge.net/resume.html
Matt W. (Guest)
on 2009-05-15 09:57
(Received via mailing list)
On 14 May 2009, at 14:20, Phlip wrote:

>> like this boring.
>
> The point of unit tests (which include the alleged "functional
> tests" in Rails) is to fail more often than production code would
> fail. Not less often.

Yep, I agree that would be silly.

On the other hand, if the tests fail for no good reason all the time
because they're fragile, people may stop listening to them, and maybe
eventually stop writing them. The argument I'm making is really just
for slowing down and taking a little more care, with the eventual
benefit of tests that are trustworthy and easy to maintain. I would
imagine that's your goal too, but we apparently have different
approaches :)

Matt W.
http://beta.songkick.com
http://blog.mattwynne.net
Phlip (Guest)
on 2009-05-15 18:56
(Received via mailing list)
Matt W. wrote:

> On the other hand, if the tests fail for no good reason all the time
> because they're fragile, people may stop listening to them, and maybe
> eventually stop writing them. The argument I'm making is really just for
> slowing down and taking a little more care, with the eventual benefit of
> tests that are trustworthy and easy to maintain. I would imagine that's
> your goal too, but we apparently have different approaches :)

The specific umbrage I took over mocking to detect a update_attribute is
I
worked for 2.5 years on a huge Rails project with hundreds of tests,
including
mocks, including controller tests that went a little too far, including
very
fragile tests, and I never once had the inclination to mock
update_attribute.
The real attribute is just so easy to detect!

Run fragile tests more often and revert more often.

--
   Phlip
   http://flea.sourceforge.net/resume.html
This topic is locked and can not be replied to.