diff --git a/CHANGELOG.md b/CHANGELOG.md index d24d347f..3a657701 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +### Added +- Allow `bashunit::spy` to accept an optional exit code (e.g. `bashunit::spy thing 1`) or custom implementation function (e.g. `bashunit::spy thing mock_thing`) (#600) + ### Fixed - Fix spying on `echo` or `printf` causing bashunit to hang due to infinite recursion (#607) diff --git a/src/test_doubles.sh b/src/test_doubles.sh index df4f60a3..c1d6d253 100644 --- a/src/test_doubles.sh +++ b/src/test_doubles.sh @@ -44,6 +44,7 @@ function bashunit::mock() { function bashunit::spy() { local command=$1 + local exit_code_or_impl="${2:-}" local variable variable="$(bashunit::helper::normalize_variable_name "$command")" @@ -56,6 +57,13 @@ function bashunit::spy() { export "${variable}_times_file"="$times_file" export "${variable}_params_file"="$params_file" + local body_suffix="" + if [[ "$exit_code_or_impl" =~ ^[0-9]+$ ]]; then + body_suffix="return $exit_code_or_impl" + elif [ -n "$exit_code_or_impl" ]; then + body_suffix="$exit_code_or_impl \"\$@\"" + fi + eval "function $command() { local raw=\"\$*\" local serialized=\"\" @@ -69,6 +77,7 @@ function bashunit::spy() { _c=\$(cat '$times_file' 2>/dev/null || builtin echo 0) _c=\$((_c+1)) builtin echo \"\$_c\" > '$times_file' + $body_suffix }" export -f "${command?}" diff --git a/tests/unit/test_doubles_test.sh b/tests/unit/test_doubles_test.sh index 9a6e6530..85a90d5f 100644 --- a/tests/unit/test_doubles_test.sh +++ b/tests/unit/test_doubles_test.sh @@ -216,3 +216,54 @@ function test_unsuccessful_spy_nth_called_with_invalid_index() { } + +function test_spy_with_exit_code_returns_specified_exit_code() { + bashunit::spy ps 1 + + local actual_exit_code=0 + ps || actual_exit_code=$? + + assert_have_been_called ps + assert_same "1" "$actual_exit_code" +} + +function test_spy_with_exit_code_zero_returns_zero() { + bashunit::spy ps 0 + + ps + local actual_exit_code=$? + + assert_have_been_called ps + assert_same "0" "$actual_exit_code" +} + +function test_spy_with_impl_calls_custom_function() { + custom_ps_impl() { + builtin echo "custom output" + } + export -f custom_ps_impl + + bashunit::spy ps custom_ps_impl + + local output + output=$(ps) + + assert_have_been_called ps + assert_same "custom output" "$output" +} + +function test_spy_with_impl_records_calls_and_delegates() { + custom_ps_impl() { + builtin echo "delegated" + } + export -f custom_ps_impl + + bashunit::spy ps custom_ps_impl + + ps first + ps second + + assert_have_been_called_times 2 ps + assert_have_been_called_nth_with 1 ps "first" + assert_have_been_called_nth_with 2 ps "second" +}