From 20bf1ef6757258619678e5ee00b8a2c6d742e1f1 Mon Sep 17 00:00:00 2001
From: Tang Chen <tangchen@cn.fujitsu.com>
Date: Sat, 14 Nov 2015 14:38:12 +0800
Subject: [PATCH] Enable FakeResource to fake methods.

Use MagicMock to fake a method in FakeResource. A new function:

    add_method(name, return_value)

is added to FakeResource. The caller specifies method @name and @return_value,
the function will add an attribute with @name, which is a callable MagicMock
object whose return value is @return_value.

When user access the attribute with a (), @return_value will be returned by
MagicMock, which looks like a function call.

Change-Id: I12eb876cbebab064773df7b5dd612de69bbf3f01
Implements: blueprint osc-unit-test-framework-improvement
---
 openstackclient/tests/fakes.py | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/openstackclient/tests/fakes.py b/openstackclient/tests/fakes.py
index 0f5ef74aa0..9f4dcc50b5 100644
--- a/openstackclient/tests/fakes.py
+++ b/openstackclient/tests/fakes.py
@@ -14,6 +14,7 @@
 #
 
 import json
+import mock
 import six
 import sys
 
@@ -122,17 +123,41 @@ class FakeModule(object):
 
 
 class FakeResource(object):
-    def __init__(self, manager, info, loaded=False):
+    def __init__(self, manager=None, info={}, loaded=False, methods={}):
+        """Set attributes and methods for a resource.
+
+        :param manager:
+            The resource manager
+        :param Dictionary info:
+            A dictionary with all attributes
+        :param bool loaded:
+            True if the resource is loaded in memory
+        :param Dictionary methods:
+            A dictionary with all methods
+        """
         self.__name__ = type(self).__name__
         self.manager = manager
         self._info = info
         self._add_details(info)
+        self._add_methods(methods)
         self._loaded = loaded
 
     def _add_details(self, info):
         for (k, v) in six.iteritems(info):
             setattr(self, k, v)
 
+    def _add_methods(self, methods):
+        """Fake methods with MagicMock objects.
+
+        For each <@key, @value> pairs in methods, add an callable MagicMock
+        object named @key as an attribute, and set the mock's return_value to
+        @value. When users access the attribute with (), @value will be
+        returned, which looks like a function call.
+        """
+        for (name, ret) in six.iteritems(methods):
+            method = mock.MagicMock(return_value=ret)
+            setattr(self, name, method)
+
     def __repr__(self):
         reprkeys = sorted(k for k in self.__dict__.keys() if k[0] != '_' and
                           k != 'manager')