Issue #23581: Add matmul support to MagicMock.

Patch by Håkan Lövdahl.
diff --git a/NEWS b/NEWS
index 89fdcc0..6278fba 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,5 @@
+- Issue #23581: Add matmul support to MagicMock. Patch by Håkan Lövdahl.
+
 - Issue #23326: Removed __ne__ implementations.  Since fixing default __ne__
   implementation in issue #21408 they are redundant. **** NOT BACKPORTED ****
 
diff --git a/mock.py b/mock.py
index e289a6e..54bd4ac 100644
--- a/mock.py
+++ b/mock.py
@@ -1806,7 +1806,7 @@
 )
 
 numerics = (
-    "add sub mul div floordiv mod lshift rshift and xor or pow"
+    "add sub mul matmul div floordiv mod lshift rshift and xor or pow"
 )
 if inPy3k:
     numerics += ' truediv'
diff --git a/tests/testmagicmethods.py b/tests/testmagicmethods.py
index ca67268..27b2981 100644
--- a/tests/testmagicmethods.py
+++ b/tests/testmagicmethods.py
@@ -17,6 +17,7 @@
 
 import inspect
 import sys
+import textwrap
 from mock import Mock, MagicMock, _magics
 
 
@@ -482,6 +483,20 @@
         self.assertEqual(list(m), [4, 5, 6])
         self.assertEqual(list(m), [])
 
+    @unittest.skipIf(sys.version_info < (3, 5), "@ added in Python 3.5")
+    def test_matmul(self):
+        src = textwrap.dedent("""\
+            m = MagicMock()
+            self.assertIsInstance(m @ 1, MagicMock)
+            m.__matmul__.return_value = 42
+            m.__rmatmul__.return_value = 666
+            m.__imatmul__.return_value = 24
+            self.assertEqual(m @ 1, 42)
+            self.assertEqual(1 @ m, 666)
+            m @= 24
+            self.assertEqual(m, 24)
+        """)
+        exec(src)
 
 if __name__ == '__main__':
     unittest.main()