diff --git a/README.rst b/README.rst
index e2e149258f99574553a3eb2fd6a48a7939deab80..bd3a301450f2982e525edf3363a1560c7aa2a8cd 100644
--- a/README.rst
+++ b/README.rst
@@ -180,7 +180,7 @@ Creating a spy that reroutes to a fake function
 
     agency.spy_on(obj.function, call_fake=my_fake_function)
 
-    # Or, in KGB 6+
+    # Or, in kgb 6+
     @agency.spy_for(obj.function)
     def _my_fake_function(some_param, *args, **kwargs):
         ...
@@ -395,7 +395,7 @@ Plan a spy operation
 
 Why start from scratch when setting up a spy? Let's plan an operation.
 
-(Spy operations are only available in KGB 6 or higher.)
+(Spy operations are only available in kgb 6 or higher.)
 
 
 Raise an exception when called
@@ -405,6 +405,15 @@ Raise an exception when called
 
    spy_on(pen.emit_poison, op=kgb.SpyOpRaise(PoisonEmptyError()))
 
+Or go nuts, have a different exception for each call (in kgb 6.1+):
+
+.. code-block:: python
+   spy_on(pen.emit_poison, op=kgb.SpyOpRaiseInOrder([
+       PoisonEmptyError(),
+       Kaboom(),
+       MissingPenError(),
+   ]))
+
 
 Or return a value
 -----------------
@@ -413,6 +422,16 @@ Or return a value
 
    spy_on(our_agent.get_identity, op=kgb.SpyOpReturn('nobody...'))
 
+Maybe a different value for each call (in kgb 6.1+)?
+
+.. code-block:: python
+
+   spy_on(our_agent.get_identity, op=kgb.SpyOpReturnInOrder([
+       'nobody...',
+       'who?',
+       'not telling...',
+   ]))
+
 
 Now for something more complicated.
 
diff --git a/kgb/__init__.py b/kgb/__init__.py
index 00101cda67e25248beaf913b31b26e1f459aa6d2..5d6f0c0762bc278c035a7bea2949e6eb3593aa30 100644
--- a/kgb/__init__.py
+++ b/kgb/__init__.py
@@ -2,7 +2,12 @@ from __future__ import unicode_literals
 
 from kgb.agency import SpyAgency
 from kgb.contextmanagers import spy_on
-from kgb.ops import SpyOpMatchAny, SpyOpMatchInOrder, SpyOpRaise, SpyOpReturn
+from kgb.ops import (SpyOpMatchAny,
+                     SpyOpMatchInOrder,
+                     SpyOpRaise,
+                     SpyOpRaiseInOrder,
+                     SpyOpReturn,
+                     SpyOpReturnInOrder)
 
 
 # The version of kgb
@@ -59,7 +64,9 @@ __all__ = [
     'SpyOpMatchAny',
     'SpyOpMatchInOrder',
     'SpyOpRaise',
+    'SpyOpRaiseInOrder',
     'SpyOpReturn',
+    'SpyOpReturnInOrder',
     'VERSION',
     'get_package_version',
     'get_version_string',
diff --git a/kgb/ops.py b/kgb/ops.py
index 8ad4c7d0101a44adffb5568bd6b70a55d1208ab2..7d7dee82d5c07f18a270941c6b54ea51b88e660b 100644
--- a/kgb/ops.py
+++ b/kgb/ops.py
@@ -551,6 +551,35 @@ class SpyOpRaise(BaseSpyOperation):
         raise self.exc
 
 
+class SpyOpRaiseInOrder(SpyOpMatchInOrder):
+    """An operation for raising exceptions in the order of calls.
+
+    This is similar to :py:class:`SpyOpRaise`, but will raise a different
+    exception for each call, based on a provided list.
+
+    Example:
+        spy_on(our_agent.get_identities, op=SpyOpRaiseInOrder([
+            PoisonEmptyError(),
+            Kaboom(),
+            MissingPenError(),
+        ]))
+    """
+
+    def __init__(self, exceptions):
+        """Initialize the operation.
+
+        Args:
+            exceptions (list of Exception):
+                The list of exceptions, one for each function call.
+        """
+        super(SpyOpRaiseInOrder, self).__init__([
+            {
+                'op': SpyOpRaise(exc),
+            }
+            for exc in exceptions
+        ])
+
+
 class SpyOpReturn(BaseSpyOperation):
     """An operation for returning a value.
 
@@ -587,3 +616,32 @@ class SpyOpReturn(BaseSpyOperation):
             The return value provided to the operation.
         """
         return self.return_value
+
+
+class SpyOpReturnInOrder(SpyOpMatchInOrder):
+    """An operation for returning a value.
+
+    This is similar to :py:class:`SpyOpReturn`, but will return a different
+    value for each call, based on a provided list.
+
+    Example:
+        spy_on(our_agent.get_identities, op=SpyOpReturnInOrder([
+            'nobody...',
+            'who?',
+            'never heard of them...',
+        ]))
+    """
+
+    def __init__(self, return_values):
+        """Initialize the operation.
+
+        Args:
+            return_values (list):
+                The list of values, one for each function call.
+        """
+        super(SpyOpReturnInOrder, self).__init__([
+            {
+                'op': SpyOpReturn(value),
+            }
+            for value in return_values
+        ])
diff --git a/kgb/tests/test_ops.py b/kgb/tests/test_ops.py
index c0f4341e26a0b5b26b48a2de91db25f13e9c99de..f2de9c9aa34147d5295a20830f43b497b808d2ee 100644
--- a/kgb/tests/test_ops.py
+++ b/kgb/tests/test_ops.py
@@ -5,7 +5,12 @@ from __future__ import unicode_literals
 import re
 
 from kgb.errors import UnexpectedCallError
-from kgb.ops import SpyOpMatchAny, SpyOpMatchInOrder, SpyOpRaise, SpyOpReturn
+from kgb.ops import (SpyOpMatchAny,
+                     SpyOpMatchInOrder,
+                     SpyOpRaise,
+                     SpyOpRaiseInOrder,
+                     SpyOpReturn,
+                     SpyOpReturnInOrder)
 from kgb.tests.base import MathClass, TestCase
 
 
@@ -628,3 +633,83 @@ class SpyOpReturnTests(TestCase):
         obj = MathClass()
 
         self.assertEqual(obj.do_math(a=4, b=3), 'abc123')
+
+
+class SpyOpReturnInOrderTests(TestCase):
+    """Unit tests for kgb.ops.SpyOpReturnInOrder."""
+
+    def test_with_function(self):
+        """Testing SpyOpReturnInOrder with function"""
+        def do_math(a, b):
+            return a + b
+
+        self.agency.spy_on(
+            do_math,
+            op=SpyOpReturnInOrder([
+                'abc123',
+                'def456',
+                'ghi789',
+            ]))
+
+        self.assertEqual(do_math(5, 3), 'abc123')
+        self.assertEqual(do_math(5, 3), 'def456')
+        self.assertEqual(do_math(5, 3), 'ghi789')
+
+        message = re.escape(
+            "do_math was called 4 time(s), but only 3 call(s) were expected. "
+            "Latest call: <SpyCall(args=(5, 3), kwargs={}, returned=None, "
+            "raised=None)>"
+        )
+
+        with self.assertRaisesRegexp(UnexpectedCallError, message):
+            do_math(5, 3)
+
+    def test_with_classmethod(self):
+        """Testing SpyOpReturnInOrder with classmethod"""
+        self.agency.spy_on(
+            MathClass.class_do_math,
+            owner=MathClass,
+            op=SpyOpReturnInOrder([
+                'abc123',
+                'def456',
+                'ghi789',
+            ]))
+
+        self.assertEqual(MathClass.class_do_math(5, 3), 'abc123')
+        self.assertEqual(MathClass.class_do_math(5, 3), 'def456')
+        self.assertEqual(MathClass.class_do_math(5, 3), 'ghi789')
+
+        message = re.escape(
+            "class_do_math was called 4 time(s), but only 3 call(s) were "
+            "expected. Latest call: <SpyCall(args=(), kwargs={'a': 5, "
+            "'b': 3}, returned=None, raised=None)>"
+        )
+
+        with self.assertRaisesRegexp(UnexpectedCallError, message):
+            MathClass.class_do_math(5, 3)
+
+    def test_with_unbound_method(self):
+        """Testing SpyOpReturnInOrder with unbound method"""
+        self.agency.spy_on(
+            MathClass.do_math,
+            owner=MathClass,
+            op=SpyOpReturnInOrder([
+                'abc123',
+                'def456',
+                'ghi789',
+            ]))
+
+        obj = MathClass()
+
+        self.assertEqual(obj.do_math(a=4, b=3), 'abc123')
+        self.assertEqual(obj.do_math(a=4, b=3), 'def456')
+        self.assertEqual(obj.do_math(a=4, b=3), 'ghi789')
+
+        message = re.escape(
+            "do_math was called 4 time(s), but only 3 call(s) were "
+            "expected. Latest call: <SpyCall(args=(), kwargs={'a': 4, "
+            "'b': 3}, returned=None, raised=None)>"
+        )
+
+        with self.assertRaisesRegexp(UnexpectedCallError, message):
+            obj.do_math(a=4, b=3)
