예제 #1
0
파일: test_spy_log.py 프로젝트: mcous/decoy
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),
        ),
    ]
예제 #2
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))
예제 #3
0
파일: test_spy_log.py 프로젝트: mcous/decoy
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
예제 #4
0
파일: test_spy_log.py 프로젝트: mcous/decoy
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
예제 #5
0
파일: test_spy_log.py 프로젝트: mcous/decoy
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
예제 #6
0
def test_when_then_return_multiple_values(
    decoy: Decoy,
    spy_log: SpyLog,
    stub_store: StubStore,
    subject: DecoyCore,
) -> None:
    """It should add multiple return values to a stub."""
    rehearsal = WhenRehearsal(spy_id=1,
                              spy_name="my_spy",
                              payload=SpyCall(args=(), kwargs={}))
    decoy.when(spy_log.consume_when_rehearsal(
        ignore_extra_args=False)).then_return(rehearsal)

    result = subject.when(0, ignore_extra_args=False)
    result.then_return(42, 43, 44)

    decoy.verify(
        stub_store.add(
            rehearsal=rehearsal,
            behavior=StubBehavior(return_value=44, once=False),
        ),
        stub_store.add(
            rehearsal=rehearsal,
            behavior=StubBehavior(return_value=43, once=True),
        ),
        stub_store.add(
            rehearsal=rehearsal,
            behavior=StubBehavior(return_value=42, once=True),
        ),
    )
예제 #7
0
파일: test_spy_log.py 프로젝트: mcous/decoy
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)
예제 #8
0
파일: test_spy_log.py 프로젝트: mcous/decoy
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]
예제 #9
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(),
    )
예제 #10
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))
예제 #11
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)
예제 #12
0
파일: test_spy_log.py 프로젝트: mcous/decoy
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)
예제 #13
0
파일: test_spy_log.py 프로젝트: mcous/decoy
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),
        ),
    ]
예제 #14
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))
예제 #15
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))
예제 #16
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))
예제 #17
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))
예제 #18
0
def test_when_ignore_extra_args(
    decoy: Decoy,
    spy_log: SpyLog,
    stub_store: StubStore,
    subject: DecoyCore,
) -> None:
    """It should be able to register a new stubbing."""
    rehearsal = WhenRehearsal(spy_id=1,
                              spy_name="my_spy",
                              payload=SpyCall(args=(), kwargs={}))
    decoy.when(spy_log.consume_when_rehearsal(
        ignore_extra_args=True)).then_return(rehearsal)

    result = subject.when("__rehearsal__", ignore_extra_args=True)
    result.then_return("hello")

    decoy.verify(
        stub_store.add(
            rehearsal=rehearsal,
            behavior=StubBehavior(return_value="hello", once=False),
        ))
예제 #19
0
def test_when_then_raise(
    decoy: Decoy,
    spy_log: SpyLog,
    stub_store: StubStore,
    subject: DecoyCore,
) -> None:
    """It should add a raise behavior to a stub."""
    rehearsal = WhenRehearsal(spy_id=1,
                              spy_name="my_spy",
                              payload=SpyCall(args=(), kwargs={}))
    decoy.when(spy_log.consume_when_rehearsal(
        ignore_extra_args=False)).then_return(rehearsal)

    error = RuntimeError("oh no")
    result = subject.when("__rehearsal__", ignore_extra_args=False)
    result.then_raise(error)

    decoy.verify(
        stub_store.add(
            rehearsal=rehearsal,
            behavior=StubBehavior(error=error),
        ))
예제 #20
0
def test_when_then_do(
    decoy: Decoy,
    spy_log: SpyLog,
    stub_store: StubStore,
    subject: DecoyCore,
) -> None:
    """It should add an action behavior to a stub."""
    rehearsal = WhenRehearsal(spy_id=1,
                              spy_name="my_spy",
                              payload=SpyCall(args=(), kwargs={}))
    decoy.when(spy_log.consume_when_rehearsal(
        ignore_extra_args=False)).then_return(rehearsal)

    action = lambda: "hello world"  # noqa: E731
    result = subject.when("__rehearsal__", ignore_extra_args=False)
    result.then_do(action)

    decoy.verify(
        stub_store.add(
            rehearsal=rehearsal,
            behavior=StubBehavior(action=action),
        ))
예제 #21
0
파일: test_spy_log.py 프로젝트: mcous/decoy
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()
예제 #22
0
파일: test_spy_log.py 프로젝트: mcous/decoy
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 == []
예제 #23
0
파일: test_spy_log.py 프로젝트: mcous/decoy
def test_clear() -> None:
    """It can clear 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)
    subject.clear()

    assert subject.get_all() == []