{"id":1575,"date":"2010-12-28T16:55:19","date_gmt":"2010-12-28T18:55:19","guid":{"rendered":"http:\/\/blog.plataformatec.com.br\/?p=1575"},"modified":"2010-12-28T16:55:19","modified_gmt":"2010-12-28T18:55:19","slug":"acceptance-tests-for-omniauth","status":"publish","type":"post","link":"https:\/\/blog.plataformatec.com.br\/2010\/12\/acceptance-tests-for-omniauth\/","title":{"rendered":"Acceptance tests for OmniAuth"},"content":{"rendered":"

One of the great gems released in the past few months was OmniAuth<\/a>. It is very easy to use, it works without tons of configurations (unless configuring XML files is your thing) and there are already plenty of resources<\/a> about it<\/a> on the internet.<\/p>\n

However, it is not easy to do acceptance tests with Omniauth as it depends on external services to work. So what should we do? When I face a scenario like this, I split the acceptance test in two parts: one before the external service and one after the external service response.<\/p>\n

Testing the first one is trivial: you only have to ensure there is an <a> tag with href equals to “\/auth\/facebook” (or “\/auth\/#{insert_your_provider_here}” if you use another one). We don’t test any of the redirects done by OmniAuth internals, because it is already tested in gem’s tests, so we go to the next step: testing the OmniAuth callback.<\/p>\n

Testing OmniAuth callbacks is in general cumbersome but for OAuth2 providers it is a bit easier as it uses Faraday<\/a> internally to connect to the provider. With Faraday, we can configure a test adapter and stub calls to return what we want.<\/p>\n

The OmniAuth strategy provides an entry point to the Faraday connection, but we don’t have an access to the strategy directly, so we need to store it globally. For a Facebook strategy, we can achieve it as below whenever configuring Omniauth middleware:<\/p>\n

\r\nmodule OmniAuth\r\n  mattr_accessor :facebook_strategy\r\nend\r\n\r\nmiddleware.use OmniAuth::Strategies::Facebook, \"APP_ID\", \"APP_SECRET\" do |strategy|\r\n  OmniAuth.facebook_strategy = strategy\r\nend<\/pre>\n

Note you will need OmniAuth 0.2.0 (which currently is OmniAuth master) as previous versions don’t yield a block on initialization like above.<\/p>\n

With access to the strategy, we do the acceptance test. First, we define the hashes we will return on the Faraday<\/a> responses.<\/p>\n

FACEBOOK_INFO = {\r\n  :id =>; '12345',\r\n  :link => 'http:\/\/facebook.com\/plataformatec',\r\n  :email => 'myemail@example.com',\r\n  :first_name => 'Plataforma',\r\n  :last_name => 'Tecnologia',\r\n  :website => 'http:\/\/blog.plataformatec.com.br'\r\n}\r\n\r\nACCESS_TOKEN = {\r\n  :access_token => \"nevergonnagiveyouup\"\r\n}<\/pre>\n

Now, we will define the stubs. OAuth2 strategies do two requests: one to retrieve the access token and another to retrieve the user information. In this example, let’s stub the Facebook requests and assign these stubs to a new connection.<\/p>\n

stubs = Faraday::Adapter::Test::Stubs.new do |b|\r\n  b.post('\/oauth\/access_token') { [200, {}, ACCESS_TOKEN.to_json] }\r\n  b.get('\/me?access_token=nevergonnagiveyouup') { [200, {}, FACEBOOK_INFO.to_json] }\r\nend\r\n\r\nOmniAuth.facebook_strategy.client.connection = Faraday::Connection.new do |builder|\r\n  builder.adapter :test, stubs\r\nend<\/pre>\n

For each provider the URLs may differ, so an idea is to do this on a TDD way (or you can browse through the OmniAuth source code and see the url that it requests):<\/p>\n

    \n
  1. Assign the Faraday fake connection without stubs.<\/li>\n
  2. Run your test<\/li>\n
  3. See the test to raise an exception like “No stubbed request for DESIRED_URL”.<\/li>\n
  4. Add the stubbed request with the response that you want.<\/li>\n
  5. Repeat this process until the test pass<\/li>\n<\/ol>\n

    This is what we do on acceptance tests with OmniAuth: testing before and after the access to the external services.<\/p>\n

    Another approach is to do only one test by short-circuiting the provider authentication URLs. To do that on a Rails application, you can store the provider URL on a method like “OmniAuth.facebook_url” and stub the method to return the callback URL on your test. If you happen to be using Devise<\/a>, the upcoming 1.2 version does the short-circuiting automatically for you, as you can see in Devise integration tests<\/a>.<\/p>\n

    What about you? How do you stub OmniAuth requests and responses on your applications?<\/p>\n","protected":false},"excerpt":{"rendered":"

    One of the great gems released in the past few months was OmniAuth. It is very easy to use, it works without tons of configurations (unless configuring XML files is your thing) and there are already plenty of resources about it on the internet. However, it is not easy to do acceptance tests with Omniauth … \u00bb<\/a><\/p>\n","protected":false},"author":12,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[1],"tags":[130,36,129],"aioseo_notices":[],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts\/1575"}],"collection":[{"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/comments?post=1575"}],"version-history":[{"count":33,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts\/1575\/revisions"}],"predecessor-version":[{"id":1927,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts\/1575\/revisions\/1927"}],"wp:attachment":[{"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/media?parent=1575"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/categories?post=1575"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/tags?post=1575"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}