More endpoint_location coverage.
diff --git a/openstack/client.go b/openstack/client.go
index bd82690..97556d6 100644
--- a/openstack/client.go
+++ b/openstack/client.go
@@ -134,7 +134,7 @@
 	client.TokenID = token.ID
 
 	client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
-		return V3EndpointLocator(v3Client, opts)
+		return V3EndpointURL(v3Client, opts)
 	}
 
 	return nil
diff --git a/openstack/endpoint_location.go b/openstack/endpoint_location.go
index bd1d820..5a311e4 100644
--- a/openstack/endpoint_location.go
+++ b/openstack/endpoint_location.go
@@ -52,13 +52,13 @@
 	return "", gophercloud.ErrEndpointNotFound
 }
 
-// V3EndpointLocator discovers the endpoint URL for a specific service using multiple calls against
+// V3EndpointURL discovers the endpoint URL for a specific service using multiple calls against
 // an identity v3 service endpoint. The specified EndpointOpts are used to identify a unique,
 // unambiguous endpoint to return. It's an error both when multiple endpoints match the provided
 // criteria and when none do. The minimum that can be specified is a Type, but you will also often
 // need to specify a Name and/or a Region depending on what's available on your OpenStack
 // deployment.
-func V3EndpointLocator(v3Client *gophercloud.ServiceClient, opts gophercloud.EndpointOpts) (string, error) {
+func V3EndpointURL(v3Client *gophercloud.ServiceClient, opts gophercloud.EndpointOpts) (string, error) {
 	// Discover the service we're interested in.
 	var services = make([]services3.Service, 0, 1)
 	servicePager := services3.List(v3Client, services3.ListOpts{ServiceType: opts.Type})
diff --git a/openstack/endpoint_location_test.go b/openstack/endpoint_location_test.go
index 05cecf5..4e0569a 100644
--- a/openstack/endpoint_location_test.go
+++ b/openstack/endpoint_location_test.go
@@ -1,12 +1,15 @@
 package openstack
 
 import (
+	"fmt"
+	"net/http"
 	"strings"
 	"testing"
 
 	"github.com/rackspace/gophercloud"
 	tokens2 "github.com/rackspace/gophercloud/openstack/identity/v2/tokens"
 	th "github.com/rackspace/gophercloud/testhelper"
+	fake "github.com/rackspace/gophercloud/testhelper/client"
 )
 
 // Service catalog fixtures take too much vertical space!
@@ -106,3 +109,117 @@
 	})
 	th.CheckEquals(t, err.Error(), "Unexpected availability in endpoint query: wat")
 }
+
+func setupV3Responses(t *testing.T) {
+	// Mock the service query.
+	th.Mux.HandleFunc("/services", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "GET")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+		w.Header().Add("Content-Type", "application/json")
+		fmt.Fprintf(w, `
+			{
+				"links": {
+					"next": null,
+					"previous": null
+				},
+				"services": [
+					{
+						"description": "Correct",
+						"id": "1234",
+						"name": "same",
+						"type": "same"
+					},
+					{
+						"description": "Bad Name",
+						"id": "9876",
+						"name": "different",
+						"type": "same"
+					}
+				]
+			}
+		`)
+	})
+
+	// Mock the endpoint query.
+	th.Mux.HandleFunc("/endpoints", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "GET")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+		th.TestFormValues(t, r, map[string]string{
+			"service_id": "1234",
+			"interface":  "public",
+		})
+
+		w.Header().Add("Content-Type", "application/json")
+		fmt.Fprintf(w, `
+			{
+				"endpoints": [
+					{
+						"id": "12",
+						"interface": "public",
+						"name": "the-right-one",
+						"region": "same",
+						"service_id": "1234",
+						"url": "https://correct:9000/"
+					},
+					{
+						"id": "14",
+						"interface": "public",
+						"name": "bad-region",
+						"region": "different",
+						"service_id": "1234",
+						"url": "https://bad-region:9001/"
+					}
+				],
+				"links": {
+					"next": null,
+					"previous": null
+				}
+			}
+    `)
+	})
+}
+
+func TestV3EndpointExact(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+	setupV3Responses(t)
+
+	actual, err := V3EndpointURL(fake.ServiceClient(), gophercloud.EndpointOpts{
+		Type:         "same",
+		Name:         "same",
+		Region:       "same",
+		Availability: gophercloud.AvailabilityPublic,
+	})
+	th.AssertNoErr(t, err)
+	th.CheckEquals(t, actual, "https://correct:9000/")
+}
+
+func TestV3EndpointNoService(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	th.Mux.HandleFunc("/services", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "GET")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+		w.Header().Add("Content-Type", "application/json")
+		fmt.Fprintf(w, `
+      {
+        "links": {
+          "next": null,
+          "previous": null
+        },
+        "services": []
+      }
+    `)
+	})
+
+	_, err := V3EndpointURL(fake.ServiceClient(), gophercloud.EndpointOpts{
+		Type:         "nope",
+		Name:         "same",
+		Region:       "same",
+		Availability: gophercloud.AvailabilityPublic,
+	})
+	th.CheckEquals(t, gophercloud.ErrServiceNotFound, err)
+}