diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7188f05e3276aa62cbff1381140fa57637bcd669..1ef88df5d2f43e51491ad77c8543fe9bcd8d2b53 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1 +1,3 @@
 # v2.15.5
+
+* added `expect_exception`
diff --git a/docs/coding/functions.rst b/docs/coding/functions.rst
index d0fd22cf5d7cb4d3fec431643d05d3bd86a9eeed..c68e74ee3498cf484783a1f93611420a0b5069d5 100644
--- a/docs/coding/functions.rst
+++ b/docs/coding/functions.rst
@@ -2,6 +2,8 @@
 Functions and decorators
 ========================
 
+.. autoclass:: satella.coding.expect_exception
+
 .. autofunction:: satella.coding.enum_value
 
 .. autofunction:: satella.coding.contains
diff --git a/satella/__init__.py b/satella/__init__.py
index 08ca75688f1c460f5961b8c447f200b3b31df6a3..c9353a9f1740a4a5a7200c7014798fef2a934671 100644
--- a/satella/__init__.py
+++ b/satella/__init__.py
@@ -1 +1 @@
-__version__ = '2.15.5a1'
+__version__ = '2.15.5'
diff --git a/satella/coding/__init__.py b/satella/coding/__init__.py
index 089da2f4ad56f05b6bc6aef39160d23a94c4e494..fa8cfbfae2ff088db6c2d58b445700348ecf63de 100644
--- a/satella/coding/__init__.py
+++ b/satella/coding/__init__.py
@@ -19,9 +19,11 @@ from .misc import update_if_not_none, update_key_if_none, update_attr_if_none, q
 from .overloading import overload, class_or_instancemethod
 from .recast_exceptions import rethrow_as, silence_excs, catch_exception, log_exceptions, \
     raises_exception
+from .expect_exception import expect_exception
 
 __all__ = [
     'Closeable', 'contains', 'enum_value',
+    'expect_exception',
     'overload', 'class_or_instancemethod',
     'update_if_not_none', 'DocsFromParent', 'update_key_if_none', 'queue_iterator',
     'update_attr_if_none', 'update_key_if_not_none', 'source_to_function',
diff --git a/satella/coding/expect_exception.py b/satella/coding/expect_exception.py
new file mode 100644
index 0000000000000000000000000000000000000000..06b2cc65ca97432a1bacf0c8b1ebb45c4dc534f3
--- /dev/null
+++ b/satella/coding/expect_exception.py
@@ -0,0 +1,40 @@
+from satella.coding.typing import ExceptionList
+import typing as tp
+
+
+class expect_exception:
+    """
+    A decorator to use as following:
+
+    >>> a = {'test': 2}
+    >>> with expect_exception(KeyError, ValueError, 'KeyError not raised'):
+    >>>     a['test2']
+
+    If other exception than the expected is raised, it is passed through
+
+    :param exc_to_except: a list of exceptions or a single exception to expect
+    :param else_raise: raise a particular exception if no exception is raised.
+        This should be a callable that accepts provided args and kwargs and returns
+        an exception instance.
+    :param args: args to provide to constructor
+    :param kwargs: kwargs to provide to constructor
+    """
+    __slots__ = ('exc_to_except', 'else_raise', 'else_raise_args', 'else_raise_kwargs')
+
+    def __init__(self, exc_to_except: ExceptionList, else_raise: tp.Type[Exception],
+                 *args, **kwargs):
+        self.exc_to_except = exc_to_except
+        self.else_raise = else_raise
+        self.else_raise_args = args
+        self.else_raise_kwargs = kwargs
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        if exc_type is None:
+            raise self.else_raise(*self.else_raise_args,
+                                  **self.else_raise_kwargs)
+        elif not isinstance(exc_val, self.exc_to_except):
+            return False
+        return True
diff --git a/tests/test_coding/test_debug.py b/tests/test_coding/test_debug.py
index b08c641a3ac761d98205c38467a5823286acfbc6..23d405091cf802040dffaa54f1dc885197c4fa98 100644
--- a/tests/test_coding/test_debug.py
+++ b/tests/test_coding/test_debug.py
@@ -1,13 +1,30 @@
 import unittest
 
 from satella.coding import precondition, short_none, has_keys, update_if_not_none, postcondition, \
-    get_arguments
+    get_arguments, expect_exception
 from satella.coding.decorators import for_argument
 from satella.exceptions import PreconditionError
 
 
 class TestTypecheck(unittest.TestCase):
 
+    def test_except_exception(self):
+        def expect_exception_1():
+            with expect_exception(KeyError, ValueError, 'Hello world!'):
+                pass
+
+        self.assertRaises(ValueError, expect_exception_1)
+
+        a = {}
+        with expect_exception(KeyError, ValueError, 'Hello world!'):
+            a['test']
+
+        def expect_exception_2():
+            with expect_exception(KeyError, ValueError, 'Hello world!'):
+                raise TypeError()
+
+        self.assertRaises(TypeError, expect_exception_2)
+
     def test_for_argument_bug(self):
         class Device:
             @for_argument(None, str)