Start learning free

LESSON 139 OF 173 · BACKEND: TESTS AND RUNNING IT

Test the Login

Practice

A route behind a login has two jobs: keep out anyone without a valid token, and let in someone who logged in. A bug can break either job, so a good test suite checks both sides.

The token is random, a new one at every login, so a test can't type it in. It does what a real client does: it logs in, reads the token from the answer, and sends it back in the Authorization header, written as Bearer, a space, then the token. http.Get sends a request at once and can't add a header, so you build the request with http.NewRequest, set its header, and send it with http.DefaultClient.Do, like in this call to another route:

request, _ := http.NewRequest("GET", s.server.URL+"/orders", nil)
request.Header.Set("Authorization", "Bearer "+token)
response, _ := http.DefaultClient.Do(request)

Here, TestMeWithoutToken already checks that GET /me answers 401 when there's no token. The check runs your tests on the shop and on two broken copies: one whose /me forgets to cut "Bearer " off the header, so it keeps everyone out, and one that lets everyone in. When you're done, Run prints:

Your tests on the shop:
  TestMeAfterLogin ... ok
  TestMeWithoutToken ... ok
  2 tests: OK
Your tests on a copy whose /me forgets to cut "Bearer " off the header:
  TestMeAfterLogin ... FAIL
    Not equal: expected map[email:ana@example.com id:1], actual map[error:Login required]
  TestMeWithoutToken ... ok
  2 tests: 1 failed, so they caught this bug
Your tests on a copy whose /me lets everyone in, even without a token:
  TestMeAfterLogin ... ok
  TestMeWithoutToken ... FAIL
    Not equal: expected 401, actual 200
  2 tests: 1 failed, so they caught this bug

Your task: below TestMeWithoutToken, write the method TestMeAfterLogin. Log Ana in with POST /login (email ana@example.com, password secret123), read her token from the answer, call GET /me with it, and check with s.Equal that the decoded answer is map[string]any{"id": 1, "email": "ana@example.com"}.


Assignment
Follow the Coding Tutorial to write a test that logs in, keeps the token and calls /me with it.


Hint
Decode the login answer into a map[string]string and read login["token"]. The header's value is the text "Bearer ", with its space, plus the token. Go won't compile a variable that's never used, so between some steps Run shows declared and not used until the next step uses it.


STEP 1 OF 10
    Ctrl + Enter to check