Home > Blockchain >  rails minitest stubbing to assert alternate method
rails minitest stubbing to assert alternate method

Time:12-21

A method replies upon two distinct APIs for geolocation, the second serving as a backup:

def admin_create
  @user_object =  User.create!(user_params)
  set_area(@user_object)
end

def set_area(resource)
  do_geocode_lookup(resource)
  if !resource.lon
    do_alternate_geocode_lookup(resource)
  end
end

Finding a data set that returns an empty lon/lat set is challenging (and orthodoxy pushes one to write the test first), so.. Is there a way to stub the test so that

  • do_geocode_lookup returns empty lon lat values
  • do_alternate_geocode_lookup(resource) method gets invoked? and thus tested?
sign_in operator_user
post admin_create_users_url, params: {user: { [...] } }
assert[...]

CodePudding user response:

Using Mocha you can stub out a method so that any instance of an object returns a specified value.

For example....

Account.any_instance.stubs(:reviews_enabled).returns(:true)

It also allows you test that a method was called...

Account.any_instance.expects(:review_started)

The fact you are altering the passed in resource instead of returning something makes things a bit trickier, but I'd be tempted to have do_geocode_lookup return true if it finds something, and false otherwise, to make things a little easier to test.

def set_area(resource)
  found = do_geocode_lookup(resource)
  unless found
    found = do_alternate_geocode_lookup(resource)
  end
  found
end

Then you could do something like this in your test...

  Geocoder.any_instance.stubs(:do_geocode_lookup).returns(:false)
  Geocoder.any_instance.expects(:do_alternate_geocode_lookup)
  result = sut.set_area(user)
  

If the expected method isn't called, you get an "expected method wasn't called" error. You can get far more sophisticated with the stubs and expects, but in this case you shouldn't have to.

  • Related