diff --git a/doc/interop-test-descriptions.md b/doc/interop-test-descriptions.md
index 666af185b9f6b04feef631d730082dbb9898b717..7c153fa3fa4cf8592ac11c79d18a6e12936175e4 100644
--- a/doc/interop-test-descriptions.md
+++ b/doc/interop-test-descriptions.md
@@ -779,25 +779,38 @@ Client asserts:
 
 ### unimplemented_method
 
-Status: Ready for implementation. Blocking beta.
-
-This test verifies calling unimplemented RPC method returns the UNIMPLEMENTED status code.
+This test verifies that calling an unimplemented RPC method returns the 
+UNIMPLEMENTED status code.
 
 Server features:
 N/A
 
 Procedure:
-* Client calls `grpc.testing.UnimplementedService/UnimplementedCall` with an
-  empty request (defined as `grpc.testing.Empty`):
+* Client calls `grpc.testing.TestService/UnimplementedMethod` with an empty
+  request (defined as `grpc.testing.Empty`):
 
     ```
     {
     }
     ```
+   
+Client asserts:
+* received status code is 12 (UNIMPLEMENTED)
+
+### unimplemented_service
+
+This test verifies calling an unimplemented server returns the UNIMPLEMENTED
+status code.
+
+Server features:
+N/A
+
+Procedure:
+* Client calls `grpc.testing.UnimplementedService/UnimplementedCall` with an
+  empty request (defined as `grpc.testing.Empty`)
 
 Client asserts:
 * received status code is 12 (UNIMPLEMENTED)
-* received status message is empty or null/unset
 
 ### cancel_after_begin
 
diff --git a/src/proto/grpc/testing/test.proto b/src/proto/grpc/testing/test.proto
index b52c4cbad6ccfa8561e38021a2f0315fbbe0c284..d6ef58ab12206df6668559c8a1882d9a4c664487 100644
--- a/src/proto/grpc/testing/test.proto
+++ b/src/proto/grpc/testing/test.proto
@@ -74,6 +74,10 @@ service TestService {
   // first request.
   rpc HalfDuplexCall(stream StreamingOutputCallRequest)
       returns (stream StreamingOutputCallResponse);
+
+  // The test server will not implement this method. It will be used
+  // to test the behavior when clients call unimplemented methods.
+  rpc UnimplementedMethod(grpc.testing.Empty) returns (grpc.testing.Empty);
 }
 
 // A simple service NOT implemented at servers so clients can test for
diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc
index 999be9d8a3f03cac3ea48619705a1b5323ebb9ef..245e27b2bbae237c6e321496b6d2e0aac70eca71 100644
--- a/test/cpp/interop/client.cc
+++ b/test/cpp/interop/client.cc
@@ -79,7 +79,8 @@ DEFINE_string(test_case, "large_unary",
               "slow_consumer : single request with response streaming with "
               "slow client consumer;\n"
               "status_code_and_message: verify status code & message;\n"
-              "timeout_on_sleeping_server: deadline exceeds on stream;\n");
+              "timeout_on_sleeping_server: deadline exceeds on stream;\n"
+              "unimplemented_method: client calls an unimplemented_method;\n");
 DEFINE_string(default_service_account, "",
               "Email of GCE default service account");
 DEFINE_string(service_account_key_file, "",
@@ -149,6 +150,8 @@ int main(int argc, char** argv) {
     client.DoStatusWithMessage();
   } else if (FLAGS_test_case == "custom_metadata") {
     client.DoCustomMetadata();
+  } else if (FLAGS_test_case == "unimplemented_method") {
+    client.DoUnimplementedMethod();
   } else if (FLAGS_test_case == "cacheable_unary") {
     client.DoCacheableUnary();
   } else if (FLAGS_test_case == "all") {
@@ -168,6 +171,7 @@ int main(int argc, char** argv) {
     client.DoEmptyStream();
     client.DoStatusWithMessage();
     client.DoCustomMetadata();
+    client.DoUnimplementedMethod();
     client.DoCacheableUnary();
     // service_account_creds and jwt_token_creds can only run with ssl.
     if (FLAGS_use_tls) {
@@ -202,7 +206,8 @@ int main(int argc, char** argv) {
                                "server_compressed_unary",
                                "server_streaming",
                                "status_code_and_message",
-                               "timeout_on_sleeping_server"};
+                               "timeout_on_sleeping_server",
+                               "unimplemented_method"};
     char* joined_testcases =
         gpr_strjoin_sep(testcases, GPR_ARRAY_SIZE(testcases), "\n", NULL);
 
diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc
index e9a804ccae728b947db779810e521bd2f60252a2..effbb8a42eb391cc9b228493912ce41262096b6d 100644
--- a/test/cpp/interop/interop_client.cc
+++ b/test/cpp/interop/interop_client.cc
@@ -981,5 +981,23 @@ bool InteropClient::DoCustomMetadata() {
   return true;
 }
 
+bool InteropClient::DoUnimplementedMethod() {
+  gpr_log(GPR_DEBUG, "Sending a request for an unimplemented rpc...");
+
+  Empty request = Empty::default_instance();
+  Empty response = Empty::default_instance();
+  ClientContext context;
+
+  Status s = serviceStub_.Get()->UnimplementedMethod(
+    &context, request, &response);
+
+  if (!AssertStatusCode(s, StatusCode::UNIMPLEMENTED)) {
+    return false;
+  }
+
+  gpr_log(GPR_DEBUG, "unimplemented rpc done.");
+  return true;
+}
+
 }  // namespace testing
 }  // namespace grpc
diff --git a/test/cpp/interop/interop_client.h b/test/cpp/interop/interop_client.h
index 1e89f0987d53a1668772023b435c4e252c35cf1c..0a96e7734d8846e979895970f14ec70666f8b9eb 100644
--- a/test/cpp/interop/interop_client.h
+++ b/test/cpp/interop/interop_client.h
@@ -79,6 +79,7 @@ class InteropClient {
   bool DoEmptyStream();
   bool DoStatusWithMessage();
   bool DoCustomMetadata();
+  bool DoUnimplementedMethod();
   bool DoCacheableUnary();
   // Auth tests.
   // username is a string containing the user email