Concrete Pagers strategy :wrench:
diff --git a/collections_test.go b/collections_test.go
index c83bd38..a005fd7 100644
--- a/collections_test.go
+++ b/collections_test.go
@@ -1,45 +1,63 @@
 package gophercloud
 
 import (
-	"fmt"
+	"bytes"
+	"errors"
+	"io"
 	"net/http"
 	"reflect"
 	"testing"
 
-	"github.com/rackspace/gophercloud/testhelper"
+	"github.com/mitchellh/mapstructure"
 )
 
+type nopCloser struct {
+	io.Reader
+}
+
+func (nopCloser) Close() error { return nil }
+
+func responseWithBody(body string) (http.Response, error) {
+	return http.Response{
+		Body: nopCloser{bytes.NewReader([]byte(body))},
+	}, nil
+}
+
 // SinglePage sample and test cases.
 
-type SinglePageCollection struct {
-	results []int
+type SingleIntList struct {
+	SinglePage
 }
 
-func (c SinglePageCollection) NextPageURL() string {
-	panic("NextPageURL should never be called on a single-paged collection.")
-}
+func ExtractSingleInts(page Page) ([]int, error) {
+	var response struct {
+		Ints []int `mapstructure:"ints"`
+	}
 
-func (c SinglePageCollection) Concat(other Collection) Collection {
-	panic("Concat should never be called on a single-paged collection.")
-}
+	err := mapstructure.Decode(page.(SingleIntList).Body, &response)
+	if err != nil {
+		return nil, err
+	}
 
-func ExtractSingleInts(c Collection) []int {
-	return c.(SinglePageCollection).results
+	return response.Ints, nil
 }
 
 func setupSinglePaged() Pager {
-	return NewSinglePager(func() (Collection, error) {
-		return SinglePageCollection{results: []int{1, 2, 3}}, nil
+	return NewSinglePager(func() (http.Response, error) {
+		return responseWithBody(`{ "ints": [1, 2, 3] }`)
 	})
 }
 
 func TestEnumerateSinglePaged(t *testing.T) {
 	callCount := 0
-	err := setupSinglePaged().EachPage(func(page Collection) bool {
+	err := setupSinglePaged().EachPage(func(page Page) bool {
 		callCount++
 
 		expected := []int{1, 2, 3}
-		actual := AsSingleInts(page)
+		actual, err := ExtractSingleInts(page)
+		if err != nil {
+			t.Fatalf("Unexpected error extracting ints: %v", err)
+		}
 		if !reflect.DeepEqual(expected, actual) {
 			t.Errorf("Expected %v, but was %v", expected, actual)
 		}
@@ -54,90 +72,52 @@
 	}
 }
 
-func TestAllSinglePaged(t *testing.T) {
-	r, err := setupSinglePaged().AllPages()
-	if err != nil {
-		t.Fatalf("Unexpected error when iterating pages: %v", err)
-	}
-
-	expected := []int{1, 2, 3}
-	actual := ExtractSingleInts(r)
-	if !reflect.DeepEqual(expected, actual) {
-		t.Errorf("Expected %v, but was %v", expected, actual)
-	}
-}
-
 // LinkedPager sample and test cases.
 
-type LinkedCollection struct {
-	PaginationLinks
-
-	results []int
+type LinkedIntPage struct {
+	PaginatedLinksPage
 }
 
-func (page LinkedCollection) NextPageURL() string {
-	n := page.PaginationLinks.Next
-	if n == nil {
-		return ""
+func ExtractLinkedInts(page Page) ([]int, error) {
+	var response struct {
+		Ints []int `mapstructure:"ints"`
 	}
-	return *n
-}
 
-func (page LinkedCollection) Concat(other Collection) Collection {
-	return LinkedCollection{
-		service: page.service,
-		results: append(c.results, AsLinkedInts(other)...),
+	err := mapstructure.Decode(page.(LinkedIntPage).Body, &response)
+	if err != nil {
+		return nil, err
 	}
+
+	return response.Ints, nil
 }
 
-func AsLinkedInts(results Collection) []int {
-	return results.(LinkedCollection).results
-}
-
-func createLinked() Pager {
-	nextURL := testhelper.Server.URL + "/foo?page=2&perPage=3"
-	return CreatePager(func(url) Collection {
-		LinkedCollection{
-			PaginationLinks: PaginationLinks{Next: &nextURL},
-			results:         []int{1, 2, 3},
-		}
-	})
-}
-
-func setupLinkedResponses(t *testing.T) {
-	testhelper.Mux.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) {
-		testhelper.TestMethod(t, r, "GET")
-		testhelper.TestHeader(t, r, "X-Auth-Token", "1234")
-		w.Header().Add("Content-Type", "application/json")
-
-		r.ParseForm()
-
-		pages := r.Form["page"]
-		if len(pages) != 1 {
-			t.Errorf("Endpoint called with unexpected page: %#v", r.Form)
-		}
-
-		switch pages[0] {
-		case "2":
-			fmt.Fprintf(w, `[4, 5, 6]`)
-		case "3":
-			fmt.Fprintf(w, `[7, 8, 9]`)
+func createLinked(t *testing.T) Pager {
+	return NewLinkedPager("page1", func(url string) (http.Response, error) {
+		switch url {
+		case "page1":
+			return responseWithBody(`{ "ints": [1, 2, 3], "links": { "next": "page2" } }`)
+		case "page2":
+			return responseWithBody(`{ "ints": [4, 5, 6], "links": { "next": "page3" } }`)
+		case "page3":
+			return responseWithBody(`{ "ints": [7, 8, 9], "links": { "next": null } }`)
 		default:
-			t.Errorf("Endpoint called with unexpected page: %s", pages[0])
+			t.Fatalf("LinkedPager called with unexpected URL: %v", url)
+			return http.Response{}, errors.New("Wat")
 		}
 	})
 }
 
 func TestEnumerateLinked(t *testing.T) {
-	testhelper.SetupHTTP()
-	defer testhelper.TeardownHTTP()
-
-	setupLinkedResponses(t)
-	lc := createLinked()
+	pager := createLinked(t)
 
 	callCount := 0
-	err := EachPage(lc, func(page Collection) bool {
-		actual := AsLinkedInts(page)
+	err := pager.EachPage(func(page Page) bool {
+		actual, err := ExtractLinkedInts(page)
+		if err != nil {
+			t.Errorf("Unable to extract ints from page: %v", err)
+			return false
+		}
+
 		t.Logf("Handler invoked with %v", actual)
 
 		var expected []int
@@ -168,28 +148,3 @@
 		t.Errorf("Expected 3 calls, but was %d", callCount)
 	}
 }
-
-func TestAllLinked(t *testing.T) {
-	testhelper.SetupHTTP()
-	defer testhelper.TeardownHTTP()
-
-	setupLinkedResponses(t)
-	lc := createLinked()
-
-	all, err := AllPages(lc)
-	if err != nil {
-		t.Fatalf("Unexpected error collection all linked pages: %v", err)
-	}
-
-	actual := AsLinkedInts(all)
-	expected := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
-
-	if !reflect.DeepEqual(expected, actual) {
-		t.Errorf("Expected %v, but was %v", expected, actual)
-	}
-
-	original := []int{1, 2, 3}
-	if !reflect.DeepEqual(AsLinkedInts(lc), original) {
-		t.Errorf("AllPages modified the original page, and now it contains: %v", lc)
-	}
-}