示例#1
0
def test_get_all() -> None:
    """It can get a list of all calls and rehearsals."""
    subject = SpyLog()
    call_1 = SpyEvent(spy_id=101,
                      spy_name="spy_1",
                      payload=SpyCall(args=(), kwargs={}))
    call_2 = SpyEvent(spy_id=101,
                      spy_name="spy_1",
                      payload=SpyCall(args=(), kwargs={}))
    call_3 = SpyEvent(spy_id=202,
                      spy_name="spy_2",
                      payload=SpyCall(args=(), kwargs={}))

    subject.push(call_1)
    subject.consume_when_rehearsal(ignore_extra_args=False)
    subject.push(call_2)
    subject.push(call_3)
    subject.consume_when_rehearsal(ignore_extra_args=False)

    assert subject.get_all() == [
        WhenRehearsal(
            spy_id=101,
            spy_name="spy_1",
            payload=SpyCall(args=(), kwargs={}),
        ),
        SpyEvent(
            spy_id=101,
            spy_name="spy_1",
            payload=SpyCall(args=(), kwargs={}),
        ),
        SpyEvent(spy_id=202,
                 spy_name="spy_2",
                 payload=SpyCall(args=(), kwargs={})),
    ]
示例#2
0
def test_consume_verify_rehearsals_ignore_extra_args() -> None:
    """It should be able to pop a slice off the stack, retaining order."""
    subject = SpyLog()
    call_1 = SpyEvent(spy_id=1,
                      spy_name="spy_1",
                      payload=SpyCall(args=(), kwargs={}))
    call_2 = SpyEvent(spy_id=2,
                      spy_name="spy_2",
                      payload=SpyCall(args=(), kwargs={}))

    subject.push(call_1)
    subject.push(call_2)

    result = subject.consume_verify_rehearsals(count=2, ignore_extra_args=True)
    assert result == [
        VerifyRehearsal(
            spy_id=1,
            spy_name="spy_1",
            payload=SpyCall(args=(), kwargs={}, ignore_extra_args=True),
        ),
        VerifyRehearsal(
            spy_id=2,
            spy_name="spy_2",
            payload=SpyCall(args=(), kwargs={}, ignore_extra_args=True),
        ),
    ]
示例#3
0
def test_get_calls_to_verify_skips_prop_gets() -> None:
    """It does not return prop getters for verification."""
    subject = SpyLog()

    call_1 = SpyEvent(
        spy_id=101,
        spy_name="spy_1",
        payload=SpyPropAccess(prop_name="child",
                              access_type=PropAccessType.GET),
    )
    call_2 = PropRehearsal(
        spy_id=101,
        spy_name="spy_1",
        payload=SpyPropAccess(prop_name="child",
                              access_type=PropAccessType.GET),
    )
    call_3 = SpyEvent(
        spy_id=102,
        spy_name="spy_1.child",
        payload=SpyCall(args=(2, ), kwargs={}),
    )
    call_4 = SpyEvent(
        spy_id=102,
        spy_name="spy_1.child",
        payload=SpyPropAccess(prop_name="fizz",
                              access_type=PropAccessType.DELETE),
    )

    subject.push(call_1)
    subject.push(call_2)
    subject.push(call_3)
    subject.push(call_4)
    result = subject.get_calls_to_verify([101, 102])
    assert result == [call_3, call_4]
示例#4
0
def test_consume_verify_rehearsals_ignores_prop_gets() -> None:
    """It should be able to pop a slice off the stack, retaining order."""
    subject = SpyLog()
    call_1 = SpyEvent(spy_id=101,
                      spy_name="spy_1",
                      payload=SpyCall(args=(1, ), kwargs={}))
    call_2 = SpyEvent(
        spy_id=101,
        spy_name="spy_1",
        payload=SpyPropAccess(prop_name="child",
                              access_type=PropAccessType.GET),
    )
    call_3 = SpyEvent(
        spy_id=102,
        spy_name="spy_1.child",
        payload=SpyCall(args=(2, ), kwargs={}),
    )
    call_4 = SpyEvent(
        spy_id=102,
        spy_name="spy_1.child",
        payload=SpyPropAccess(prop_name="fizz",
                              access_type=PropAccessType.DELETE),
    )
    subject.push(call_1)
    subject.push(call_2)
    subject.push(call_3)
    subject.push(call_4)

    result = subject.consume_verify_rehearsals(count=3,
                                               ignore_extra_args=False)
    assert result == [
        VerifyRehearsal(
            spy_id=101,
            spy_name="spy_1",
            payload=SpyCall(args=(1, ), kwargs={}),
        ),
        VerifyRehearsal(
            spy_id=102,
            spy_name="spy_1.child",
            payload=SpyCall(args=(2, ), kwargs={}),
        ),
        VerifyRehearsal(
            spy_id=102,
            spy_name="spy_1.child",
            payload=SpyPropAccess(prop_name="fizz",
                                  access_type=PropAccessType.DELETE),
        ),
    ]
示例#5
0
def test_spy_prop_get(
    decoy: Decoy,
    call_handler: CallHandler,
    spy_creator: SpyCreator,
    spec: Spec,
) -> None:
    """It should record a property get call."""
    subject = Spy(spec=spec,
                  call_handler=call_handler,
                  spy_creator=spy_creator)

    decoy.when(spec.get_name()).then_return("spy_name")
    decoy.when(
        call_handler.handle(
            SpyEvent(
                spy_id=id(subject),
                spy_name="spy_name",
                payload=SpyPropAccess(
                    prop_name="some_property",
                    access_type=PropAccessType.GET,
                ),
            ), )).then_return(CallHandlerResult(42))

    result = subject.some_property

    assert result == 42
示例#6
0
def test_spy_prop_delete(
    decoy: Decoy,
    call_handler: CallHandler,
    spy_creator: SpyCreator,
    spec: Spec,
) -> None:
    """It should record a property set call."""
    decoy.when(spec.get_name()).then_return("spy_name")

    subject = Spy(spec=spec,
                  call_handler=call_handler,
                  spy_creator=spy_creator)
    subject.some_property = 42
    del subject.some_property

    assert subject.some_property != 42

    decoy.verify(
        call_handler.handle(
            SpyEvent(
                spy_id=id(subject),
                spy_name="spy_name",
                payload=SpyPropAccess(
                    prop_name="some_property",
                    access_type=PropAccessType.DELETE,
                ),
            ), ))
示例#7
0
def test_get_by_call_empty() -> None:
    """It should return None if store is empty."""
    subject = StubStore()
    result = subject.get_by_call(call=SpyEvent(
        spy_id=42, spy_name="my_spy", payload=SpyCall(args=(), kwargs={})))

    assert result is None
示例#8
0
def test_verify(
    decoy: Decoy,
    spy_log: SpyLog,
    verifier: Verifier,
    subject: DecoyCore,
) -> None:
    """It should be able to verify a call."""
    spy_id = 42
    rehearsal = VerifyRehearsal(spy_id=spy_id,
                                spy_name="my_spy",
                                payload=SpyCall(args=(), kwargs={}))
    call = SpyEvent(spy_id=spy_id,
                    spy_name="my_spy",
                    payload=SpyCall(args=(), kwargs={}))

    decoy.when(
        spy_log.consume_verify_rehearsals(
            count=1, ignore_extra_args=False)).then_return([rehearsal])

    decoy.when(spy_log.get_calls_to_verify([spy_id])).then_return([call])

    subject.verify("__rehearsal__", times=None, ignore_extra_args=False)

    decoy.verify(
        verifier.verify(rehearsals=[rehearsal], calls=[call], times=None))
示例#9
0
def test_spy_calls(
    decoy: Decoy,
    call_handler: CallHandler,
    spy_creator: SpyCreator,
    spec: Spec,
) -> None:
    """It should send any calls to the call handler."""
    subject = Spy(spec=spec,
                  call_handler=call_handler,
                  spy_creator=spy_creator)

    decoy.when(spec.get_name()).then_return("spy_name")
    decoy.when(spec.bind_args(1, 2, three=3)).then_return(
        BoundArgs(args=(1, 2, 3), kwargs={}))
    decoy.when(
        call_handler.handle(
            SpyEvent(
                spy_id=id(subject),
                spy_name="spy_name",
                payload=SpyCall(args=(1, 2, 3), kwargs={}),
            ))).then_return(CallHandlerResult(42))

    result = subject(1, 2, three=3)

    assert result == 42
示例#10
0
def test_consume_verify_rehearsals_raises_error() -> None:
    """It should raise an error if the stack has too few members to pop a slice."""
    subject = SpyLog()
    call_1 = SpyEvent(spy_id=1,
                      spy_name="spy_1",
                      payload=SpyCall(args=(), kwargs={}))

    subject.push(call_1)

    with pytest.raises(MissingRehearsalError):
        subject.consume_verify_rehearsals(count=2, ignore_extra_args=False)
示例#11
0
def test_consume_prop_rehearsal_raises_empty_error() -> None:
    """It should raise an error a valid rehearsal event isn't found."""
    subject = SpyLog()

    with pytest.raises(MissingRehearsalError):
        subject.consume_prop_rehearsal()

    event = SpyEvent(
        spy_id=42,
        spy_name="my_spy",
        payload=SpyPropAccess(prop_name="my_prop",
                              access_type=PropAccessType.GET),
    )
    subject.push(event)
    subject.consume_prop_rehearsal()

    with pytest.raises(MissingRehearsalError):
        subject.consume_prop_rehearsal()

    call = SpyEvent(
        spy_id=42,
        spy_name="my_spy",
        payload=SpyCall(args=(), kwargs={}),
    )
    subject.push(call)

    with pytest.raises(MissingRehearsalError):
        subject.consume_prop_rehearsal()

    event = SpyEvent(
        spy_id=42,
        spy_name="my_spy",
        payload=SpyPropAccess(prop_name="my_prop",
                              access_type=PropAccessType.DELETE),
    )
    subject.push(event)

    with pytest.raises(MissingRehearsalError):
        subject.consume_prop_rehearsal()
示例#12
0
def test_get_by_call() -> None:
    """It should be able to add a StubBehavior to the store and get it back."""
    subject = StubStore()
    rehearsal = WhenRehearsal(spy_id=42,
                              spy_name="my_spy",
                              payload=SpyCall(args=(), kwargs={}))
    behavior = StubBehavior(return_value="hello world")

    subject.add(rehearsal=rehearsal, behavior=behavior)
    result = subject.get_by_call(call=SpyEvent(
        spy_id=42, spy_name="my_spy", payload=SpyCall(args=(), kwargs={})))

    assert result == behavior
示例#13
0
def test_prop(
    decoy: Decoy,
    spy_log: SpyLog,
    subject: DecoyCore,
) -> None:
    """It should be able to create set and delete rehearsals."""
    rehearsal = PropRehearsal(
        spy_id=1,
        spy_name="my_spy",
        payload=SpyPropAccess(prop_name="my_prop",
                              access_type=PropAccessType.GET),
    )

    decoy.when(spy_log.consume_prop_rehearsal()).then_return(rehearsal)

    result = subject.prop("__rehearsal__")

    result.set("hello")

    expected_set_event = SpyEvent(
        spy_id=1,
        spy_name="my_spy",
        payload=SpyPropAccess(
            prop_name="my_prop",
            access_type=PropAccessType.SET,
            value="hello",
        ),
    )
    decoy.verify(spy_log.push(expected_set_event), times=1)

    result.delete()

    expected_delete_event = SpyEvent(
        spy_id=1,
        spy_name="my_spy",
        payload=SpyPropAccess(prop_name="my_prop",
                              access_type=PropAccessType.DELETE),
    )
    decoy.verify(spy_log.push(expected_delete_event), times=1)
示例#14
0
def test_get_calls_to_verify() -> None:
    """It can get a list of calls made matching spy IDs of given rehearsals."""
    subject = SpyLog()
    call_1 = SpyEvent(
        spy_id=101,
        spy_name="spy_1",
        payload=SpyCall(args=(1, ), kwargs={}),
    )
    call_2 = SpyEvent(
        spy_id=101,
        spy_name="spy_1",
        payload=SpyCall(args=(2, ), kwargs={}),
    )
    call_3 = SpyEvent(
        spy_id=202,
        spy_name="spy_2",
        payload=SpyCall(args=(1, ), kwargs={}),
    )
    call_4 = SpyEvent(
        spy_id=101,
        spy_name="spy_1",
        payload=SpyCall(args=(1, ), kwargs={}),
    )

    subject.push(call_1)
    subject.push(call_2)
    subject.consume_when_rehearsal(ignore_extra_args=False)
    subject.push(call_3)
    subject.push(call_4)

    result = subject.get_calls_to_verify([101])
    assert result == [call_1, call_4]

    result = subject.get_calls_to_verify([101, 202])
    assert result == [call_1, call_3, call_4]

    result = subject.get_calls_to_verify([303])
    assert result == []
示例#15
0
def test_push_and_consume_when_rehearsal() -> None:
    """It should be able to push and pop from the stack."""
    subject = SpyLog()
    call = SpyEvent(
        spy_id=42,
        spy_name="my_spy",
        payload=SpyCall(args=(), kwargs={}),
    )

    subject.push(call)
    result = subject.consume_when_rehearsal(ignore_extra_args=False)

    assert isinstance(result, WhenRehearsal)
    assert call == result
示例#16
0
def test_push_and_consume_prop_rehearsal_for_prop() -> None:
    """It should be able to push and consume a prop rehearsal for more rehearsals."""
    subject = SpyLog()
    event = SpyEvent(
        spy_id=42,
        spy_name="my_spy",
        payload=SpyPropAccess(prop_name="my_prop",
                              access_type=PropAccessType.GET),
    )

    subject.push(event)
    result = subject.consume_prop_rehearsal()
    assert isinstance(result, PropRehearsal)
    assert result == event
示例#17
0
def test_get_by_call_once_behavior() -> None:
    """It should consume any behavior marked with the `once` flag."""
    subject = StubStore()
    rehearsal = WhenRehearsal(spy_id=42,
                              spy_name="my_spy",
                              payload=SpyCall(args=(1, 2, 3), kwargs={}))
    behavior = StubBehavior(return_value="fizzbuzz", once=True)

    subject.add(rehearsal=rehearsal, behavior=behavior)

    result = subject.get_by_call(
        call=SpyEvent(spy_id=42,
                      spy_name="my_spy",
                      payload=SpyCall(args=(1, 2, 3), kwargs={})))

    assert result == behavior

    result = subject.get_by_call(
        call=SpyEvent(spy_id=42,
                      spy_name="my_spy",
                      payload=SpyCall(args=(1, 2, 3), kwargs={})))

    assert result is None
示例#18
0
def test_push_and_consume_prop_rehearsal_for_when() -> None:
    """It should be able to push and consume a prop rehearsal for stubbing."""
    subject = SpyLog()
    event = SpyEvent(
        spy_id=42,
        spy_name="my_spy",
        payload=SpyPropAccess(prop_name="my_prop",
                              access_type=PropAccessType.GET),
    )

    subject.push(event)
    result = subject.consume_when_rehearsal(ignore_extra_args=False)
    assert isinstance(result, WhenRehearsal)
    assert result == event
示例#19
0
def test_consume_when_rehearsal_raises_empty_error() -> None:
    """It should raise an error if the stack is empty on pop."""
    subject = SpyLog()

    with pytest.raises(MissingRehearsalError):
        subject.consume_when_rehearsal(ignore_extra_args=False)

    call = SpyEvent(
        spy_id=42,
        spy_name="my_spy",
        payload=SpyCall(args=(), kwargs={}),
    )
    subject.push(call)
    subject.consume_when_rehearsal(ignore_extra_args=False)

    with pytest.raises(MissingRehearsalError):
        subject.consume_when_rehearsal(ignore_extra_args=False)
示例#20
0
def test_handle_call_with_raise(
    decoy: Decoy,
    spy_log: SpyLog,
    stub_store: StubStore,
    subject: CallHandler,
) -> None:
    """It raise a Stub's configured error."""
    spy_call = SpyEvent(spy_id=42,
                        spy_name="spy_name",
                        payload=SpyCall(args=(), kwargs={}))
    behavior = StubBehavior(error=RuntimeError("oh no"))

    decoy.when(stub_store.get_by_call(spy_call)).then_return(behavior)

    with pytest.raises(RuntimeError, match="oh no"):
        subject.handle(spy_call)

    decoy.verify(spy_log.push(spy_call))
示例#21
0
def test_handle_call_with_return(
    decoy: Decoy,
    spy_log: SpyLog,
    stub_store: StubStore,
    subject: CallHandler,
) -> None:
    """It return a Stub's configured return value."""
    spy_call = SpyEvent(spy_id=42,
                        spy_name="spy_name",
                        payload=SpyCall(args=(), kwargs={}))
    behavior = StubBehavior(return_value="hello world")

    decoy.when(stub_store.get_by_call(spy_call)).then_return(behavior)

    result = subject.handle(spy_call)

    assert result == CallHandlerResult("hello world")
    decoy.verify(spy_log.push(spy_call))
示例#22
0
def test_handle_call_with_no_stubbing(
    decoy: Decoy,
    spy_log: SpyLog,
    stub_store: StubStore,
    subject: CallHandler,
) -> None:
    """It should noop and add the call to the stack if no stubbing is configured."""
    spy_call = SpyEvent(spy_id=42,
                        spy_name="spy_name",
                        payload=SpyCall(args=(), kwargs={}))
    behavior = None

    decoy.when(stub_store.get_by_call(spy_call)).then_return(behavior)

    result = subject.handle(spy_call)

    assert result is None
    decoy.verify(spy_log.push(spy_call))
示例#23
0
def test_handle_call_with_context_enter(
    decoy: Decoy,
    spy_log: SpyLog,
    stub_store: StubStore,
    subject: CallHandler,
) -> None:
    """It return a Stub's configured context value."""
    spy_call = SpyEvent(spy_id=42,
                        spy_name="spy_name",
                        payload=SpyCall(args=(), kwargs={}))
    behavior = StubBehavior(context_value="hello world")

    decoy.when(stub_store.get_by_call(spy_call)).then_return(behavior)

    with subject.handle(spy_call).value as result:  # type: ignore[union-attr]
        assert result == "hello world"

    decoy.verify(spy_log.push(spy_call))
示例#24
0
def test_get_by_call_prefers_latest() -> None:
    """It should be prefer later stubs if multiple exist."""
    subject = StubStore()
    rehearsal_1 = WhenRehearsal(spy_id=42,
                                spy_name="my_spy",
                                payload=SpyCall(args=(), kwargs={}))
    behavior_1 = StubBehavior(return_value="hello")
    rehearsal_2 = WhenRehearsal(spy_id=42,
                                spy_name="my_spy",
                                payload=SpyCall(args=(), kwargs={}))
    behavior_2 = StubBehavior(return_value="goodbye")

    subject.add(rehearsal=rehearsal_1, behavior=behavior_1)
    subject.add(rehearsal=rehearsal_2, behavior=behavior_2)
    result = subject.get_by_call(call=SpyEvent(
        spy_id=42, spy_name="my_spy", payload=SpyCall(args=(), kwargs={})))

    assert result == behavior_2
示例#25
0
def test_handle_call_with_action(
    decoy: Decoy,
    spy_log: SpyLog,
    stub_store: StubStore,
    subject: CallHandler,
) -> None:
    """It should trigger a stub's configured action."""
    action = decoy.mock()
    spy_call = SpyEvent(
        spy_id=42,
        spy_name="spy_name",
        payload=SpyCall(args=(1, ), kwargs={"foo": "bar"}),
    )
    behavior = StubBehavior(action=action)

    decoy.when(stub_store.get_by_call(spy_call)).then_return(behavior)
    decoy.when(action(1, foo="bar")).then_return("hello world")

    result = subject.handle(spy_call)

    assert result == CallHandlerResult("hello world")
示例#26
0
def test_reset(
    decoy: Decoy,
    spy_log: SpyLog,
    stub_store: StubStore,
    warning_checker: WarningChecker,
    subject: DecoyCore,
) -> None:
    """It should reset the stores."""
    call = SpyEvent(spy_id=1,
                    spy_name="my_spy",
                    payload=SpyCall(args=(), kwargs={}))

    decoy.when(spy_log.get_all()).then_return([call])

    subject.reset()

    decoy.verify(
        warning_checker.check([call]),
        spy_log.clear(),
        stub_store.clear(),
    )
示例#27
0
def test_handle_prop_get_with_action(
    decoy: Decoy,
    spy_log: SpyLog,
    stub_store: StubStore,
    subject: CallHandler,
) -> None:
    """It should trigger a prop get stub's configured action."""
    action = decoy.mock()
    spy_call = SpyEvent(
        spy_id=42,
        spy_name="spy_name",
        payload=SpyPropAccess(prop_name="prop",
                              access_type=PropAccessType.GET),
    )
    behavior = StubBehavior(action=action)

    decoy.when(stub_store.get_by_call(spy_call)).then_return(behavior)
    decoy.when(action()).then_return("hello world")

    result = subject.handle(spy_call)

    assert result == CallHandlerResult("hello world")
示例#28
0
def test_verify_multiple_calls(
    decoy: Decoy,
    spy_log: SpyLog,
    verifier: Verifier,
    subject: DecoyCore,
) -> None:
    """It should be able to verify a call."""
    spy_id_1 = 42
    spy_id_2 = 9001

    rehearsals = [
        VerifyRehearsal(spy_id=spy_id_1,
                        spy_name="spy_1",
                        payload=SpyCall(args=(), kwargs={})),
        VerifyRehearsal(spy_id=spy_id_2,
                        spy_name="spy_2",
                        payload=SpyCall(args=(), kwargs={})),
    ]
    calls = [
        SpyEvent(spy_id=spy_id_1,
                 spy_name="spy_1",
                 payload=SpyCall(args=(), kwargs={}))
    ]

    decoy.when(
        spy_log.consume_verify_rehearsals(
            count=2, ignore_extra_args=False)).then_return(rehearsals)
    decoy.when(spy_log.get_calls_to_verify([spy_id_1,
                                            spy_id_2])).then_return(calls)

    subject.verify(
        "__rehearsal_1__",
        "__rehearsal_2__",
        times=None,
        ignore_extra_args=False,
    )

    decoy.verify(
        verifier.verify(rehearsals=rehearsals, calls=calls, times=None))
示例#29
0
    expected_warnings: Sequence[DecoyWarning]


warning_checker_specs = [
    # it should not warn if there are no calls
    WarningCheckerSpec(
        all_calls=[],
        expected_warnings=[],
    ),
    # it should not warn if rehearsals and calls match
    WarningCheckerSpec(
        all_calls=[
            WhenRehearsal(
                spy_id=1, spy_name="spy", payload=SpyCall(args=(1,), kwargs={})
            ),
            SpyEvent(spy_id=1, spy_name="spy", payload=SpyCall(args=(1,), kwargs={})),
        ],
        expected_warnings=[],
    ),
    # it should not warn if a call is made and there are no rehearsals
    WarningCheckerSpec(
        all_calls=[
            SpyEvent(spy_id=1, spy_name="spy", payload=SpyCall(args=(1,), kwargs={})),
        ],
        expected_warnings=[],
    ),
    # it should warn if a spy has a rehearsal and a call that doesn't match
    WarningCheckerSpec(
        all_calls=[
            WhenRehearsal(
                spy_id=1, spy_name="spy", payload=SpyCall(args=(), kwargs={})
示例#30
0
     expected_message=os.linesep.join([
         "Expected at least 1 call:",
         "1.\tmy_spy()",
         "Found 0 calls.",
     ]),
 ),
 VerifyErrorSpec(
     rehearsals=[
         VerifyRehearsal(spy_id=42,
                         spy_name="my_spy",
                         payload=SpyCall(args=(), kwargs={})),
     ],
     calls=[
         SpyEvent(
             spy_id=101,
             spy_name="spy_101",
             payload=SpyCall(args=(1, 2, 3), kwargs={}),
         ),
         SpyEvent(
             spy_id=101,
             spy_name="spy_101",
             payload=SpyCall(args=(4, 5, 6), kwargs={}),
         ),
     ],
     times=None,
     expected_message=os.linesep.join([
         "Expected at least 1 call:",
         "1.\tmy_spy()",
         "Found 2 calls:",
         "1.\tspy_101(1, 2, 3)",
         "2.\tspy_101(4, 5, 6)",