# Path: doubles/exceptions.py
# class MockExpectationError(AssertionError):
#     """An exception raised when a mock fails verification."""
# 
#     pass
# 
# Path: doubles/instance_double.py
# class InstanceDouble(ObjectDouble):
#     """A pure double representing an instance of the target class.
# 
#     Any kwargs supplied will be set as attributes on the instance that is
#     created.
# 
#     ::
# 
#         user = InstanceDouble('myapp.User', name='Bob Barker')
# 
#     :param str path: The absolute module path to the class.
#     """
# 
#     def __init__(self, path, **kwargs):
#         module_path, class_name = get_path_components(path)
#         module = get_module(module_path, path)
#         self._doubles_target = _get_doubles_target(module, class_name, path)
#         for k, v in kwargs.items():
#             setattr(self, k, v)
# 
# Path: doubles/lifecycle.py
# def verify():
#     """Verify a mock
# 
#     Verifies any mocks that have been created during the test run. Must be called after each
#     test case, but before teardown.
#     """
# 
#     if hasattr(_thread_local_data, 'current_space'):
#         _thread_local_data.current_space.verify()
# 
# def teardown():
#     """Tears down the current Doubles environment. Must be called after each test case."""
#     if hasattr(_thread_local_data, 'current_space'):
#         _thread_local_data.current_space.teardown()
#         del _thread_local_data.current_space
# 
# Path: doubles/targets/allowance_target.py
# def allow(target):
#     """
#     Prepares a target object for a method call allowance (stub). The name of the method to allow
#     should be called as a method on the return value of this function::
# 
#         allow(foo).bar
# 
#     Accessing the ``bar`` attribute will return an ``Allowance`` which provides additional methods
#     to configure the stub.
# 
#     :param object target: The object that will be stubbed.
#     :return: An ``AllowanceTarget`` for the target object.
#     """
# 
#     return AllowanceTarget(target)
# 
# Path: doubles/targets/expectation_target.py
# def expect(target):
#     """
#     Prepares a target object for a method call expectation (mock). The name of the method to expect
#     should be called as a method on the return value of this function::
# 
#         expect(foo).bar
# 
#     Accessing the ``bar`` attribute will return an ``Expectation`` which provides additional methods
#     to configure the mock.
# 
#     :param object target: The object that will be mocked.
#     :return: An ``ExpectationTarget`` for the target object.
#     """
# 
#     return ExpectationTarget(target)


import re
from pytest import raises
from doubles.exceptions import MockExpectationError
from doubles.instance_double import InstanceDouble
from doubles.lifecycle import verify, teardown
from doubles.targets.allowance_target import allow
from doubles.targets.expectation_target import expect
            r"<InstanceDouble of <class 'doubles.testing.User'> object at .+> "
            r"with any args, but was not."
            r" \(.*doubles/test/expect_test.py:\d+\)",
            str(e.value)
        )


class TestNever(object):
    def test_passes_when_called_never(self):
        subject = InstanceDouble('doubles.testing.User')

        expect(subject).instance_method.never()


class TestExactly(object):
    def test_calls_are_chainable(self):
        subject = InstanceDouble('doubles.testing.User')

        expect(subject).instance_method.exactly(1).times.exactly(2).times

        subject.instance_method()
        subject.instance_method()

    def test_fails_when_called_less_than_expected_times(self):
        subject = InstanceDouble('doubles.testing.User')

        expect(subject).instance_method.exactly(2).times

        subject.instance_method()
        with raises(MockExpectationError) as e:

# Path: doubles/exceptions.py
# class MockExpectationError(AssertionError):
#     """An exception raised when a mock fails verification."""
# 
#     pass
# 
# Path: doubles/instance_double.py
# class InstanceDouble(ObjectDouble):
#     """A pure double representing an instance of the target class.
# 
#     Any kwargs supplied will be set as attributes on the instance that is
#     created.
# 
#     ::
# 
#         user = InstanceDouble('myapp.User', name='Bob Barker')
# 
#     :param str path: The absolute module path to the class.
#     """
# 
#     def __init__(self, path, **kwargs):
#         module_path, class_name = get_path_components(path)
#         module = get_module(module_path, path)
#         self._doubles_target = _get_doubles_target(module, class_name, path)
#         for k, v in kwargs.items():
#             setattr(self, k, v)
# 
# Path: doubles/lifecycle.py
# def verify():
#     """Verify a mock
# 
#     Verifies any mocks that have been created during the test run. Must be called after each
#     test case, but before teardown.
#     """
# 
#     if hasattr(_thread_local_data, 'current_space'):
#         _thread_local_data.current_space.verify()
# 
# def teardown():
#     """Tears down the current Doubles environment. Must be called after each test case."""
#     if hasattr(_thread_local_data, 'current_space'):
#         _thread_local_data.current_space.teardown()
#         del _thread_local_data.current_space
# 
# Path: doubles/targets/allowance_target.py
# def allow(target):
#     """
#     Prepares a target object for a method call allowance (stub). The name of the method to allow
#     should be called as a method on the return value of this function::
# 
#         allow(foo).bar
# 
#     Accessing the ``bar`` attribute will return an ``Allowance`` which provides additional methods
#     to configure the stub.
# 
#     :param object target: The object that will be stubbed.
#     :return: An ``AllowanceTarget`` for the target object.
#     """
# 
#     return AllowanceTarget(target)
# 
# Path: doubles/targets/expectation_target.py
# def expect(target):
#     """
#     Prepares a target object for a method call expectation (mock). The name of the method to expect
#     should be called as a method on the return value of this function::
# 
#         expect(foo).bar
# 
#     Accessing the ``bar`` attribute will return an ``Expectation`` which provides additional methods
#     to configure the mock.
# 
#     :param object target: The object that will be mocked.
#     :return: An ``ExpectationTarget`` for the target object.
#     """
# 
#     return ExpectationTarget(target)


# Path: test/expect_test.py
import re
from pytest import raises
from doubles.exceptions import MockExpectationError
from doubles.instance_double import InstanceDouble
from doubles.lifecycle import verify, teardown
from doubles.targets.allowance_target import allow
from doubles.targets.expectation_target import expect

            r"<InstanceDouble of <class 'doubles.testing.User'> object at .+> "
            r"with any args, but was not."
            r" \(.*doubles/test/expect_test.py:\d+\)",
            str(e.value)
        )


class TestNever(object):
    def test_passes_when_called_never(self):
        subject = InstanceDouble('doubles.testing.User')

        expect(subject).instance_method.never()


class TestExactly(object):
    def test_calls_are_chainable(self):
        subject = InstanceDouble('doubles.testing.User')

        expect(subject).instance_method.exactly(1).times.exactly(2).times

        subject.instance_method()
        subject.instance_method()

    def test_fails_when_called_less_than_expected_times(self):
        subject = InstanceDouble('doubles.testing.User')

        expect(subject).instance_method.exactly(2).times

        subject.instance_method()
        with raises(MockExpectationError) as e:

            verify()