Skip to content

Commit

Permalink
Merge pull request #14 from lindycoder/arg_validate
Browse files Browse the repository at this point in the history
Multi mocks + Arguments validation
  • Loading branch information
lindycoder authored Nov 25, 2016
2 parents b383522 + 1b80343 commit bf6688c
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 31 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ clean.sh
test

test_clean_works() {
mock rm --with-args "somewhere/some-file" --and exitcode 0
mock rm --with-args "somewhere/some-file" --and exit-code 0

bash ./clean.sh some-file

Expand Down
4 changes: 2 additions & 2 deletions examples/2-mocking/test/test_clean.sh
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#!/bin/bash

test_clean_works() {
mock rm --with-args "somewhere/some-file" --and exitcode 0
mock rm --with-args "somewhere/some-file" --and exit-code 0

bash ./clean.sh some-file

assert ${?} succeeded
}

test_clean_works_fails() {
mock rm --with-args "somewhere/non-existing-file" --and exitcode 1
mock rm --with-args "somewhere/non-existing-file" --and exit-code 1

bash ./clean.sh non-existing-file

Expand Down
2 changes: 1 addition & 1 deletion src/cli.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ if [ -z "${RUN_SINGLE_TEST:-""}" ]; then
registry="$(mktemp -d "/tmp/workspace.registry.XXXXXXXX")"
test_count=0

for f in $(find ${test_sources_root} -name "${test_suites_filter}"); do
for f in $(find ${test_sources_root} -name "${test_suites_filter}" | sort); do
TEST_ROOT_DIR=${test_sources_root} RUN_SINGLE_TEST=1 $0 ${sources_root} ${f} ${test_filter} ${registry} || fail "${f} failed."

new_tests=$(cat ${registry}/test_count)
Expand Down
112 changes: 85 additions & 27 deletions src/mocking.sh
Original file line number Diff line number Diff line change
@@ -1,47 +1,105 @@
action-echo() {
text="$@"
cat <<EOF
echo "${text}"
EOF
}

mock-exitcode() {
action-exit-code() {
return_code=$1
cat <<EOF
#!/bin/bash
exit ${return_code}
EOF
}

validate-args() {
expected="$@"
cat <<EOF
args="\$@"
if [ "\${args}" != "${expected}" ]; then
cat <<OUT
Unexpected invocation for command 'some-command':
Got : <"\${args}">
Expected : <"${expected}">
OUT
exit 1
fi
EOF
}

mock() {
local expected_args=""
local mock_type=""
local and_params=""
local executable=$1; shift
local actions=()
local actions_params=()
local action_count=0
local has_args_validation=false

local executable=$1; shift;
if [ $1 == "--with-args" ]; then
expected_args=$2; shift; shift;
fi
if [ $1 == "--and" ]; then
mock_type=$2; shift; shift;
and_params=$@
fi
while [[ $# -gt 0 ]]; do
local key="$1"

case ${key} in
--and)
actions[$action_count]="action-$2"
actions_params[$action_count]="$3"
shift; shift
((action_count=action_count + 1))
;;
--with-args)
if [ ${has_args_validation} == false ]; then
actions[$action_count]="validate-args"
actions_params[$action_count]="$2"; shift
((action_count=action_count + 1))
has_args_validation=true
else
echo "Cannot expect more than 1 set of argument for an invocation, please use 'mock' multiple times"
return 1
fi
;;
esac
shift
done

if [ -n "${expected_args}" ]; then
_mock_assert_args "${expected_args}" ${mocks}/${executable}-then > ${mocks}/${executable}
mock ${executable}-then --and exitcode "${and_params}"
mock_workspace="${mocks}/_${executable}.workspace"

if [ ! -d ${mock_workspace} ]; then
mkdir -p ${mock_workspace}
echo "1" > ${mock_workspace}/invocation_index

_mock_handler ${mock_workspace} > ${mocks}/${executable}
chmod +x ${mocks}/${executable}

invocation_count=1
else
mock-${mock_type} "${and_params}" > ${mocks}/${executable}
((invocation_count=$(cat ${mock_workspace}/invocation_count) + 1))
fi
chmod +x ${mocks}/${executable}
}

echo ${invocation_count} > ${mock_workspace}/invocation_count
invocation_file="${mock_workspace}/invocation_${invocation_count}"

echo "#!/bin/bash" > ${invocation_file}

for i in ${!actions[@]}; do
${actions[$i]} ${actions_params[$i]} >> ${invocation_file}
done

_mock_assert_args() {
expected_args=$1
and=$2
chmod +x ${invocation_file}
}

_mock_handler() {
cat <<EOF
#!/bin/bash
args=\$@
if [ "\$args" == "${expected_args}" ]; then
${and}
else
echo "Args [\$args] did not match [${expected_args}]" > expectation_failure
args="\$@"
workspace=$1
invocation_index=\$(cat \${workspace}/invocation_index)
if [ \${invocation_index} -lt \$(cat \${workspace}/invocation_count) ]; then
echo \$((invocation_index + 1)) > \${workspace}/invocation_index
fi
\${workspace}/invocation_\${invocation_index} \${args}
EOF
}
23 changes: 23 additions & 0 deletions test/test_mocking_args_matching.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash

test_fails_if_given_arguments_isnt_right() {
mock some-command --with-args "one two three"

some-command three two one > assertion_output
assert ${?} failed

expected_error=$(cat <<-EXP
Unexpected invocation for command 'some-command':
Got : <"three two one">
Expected : <"one two three">
EXP
)
assert "$(cat assertion_output)" equals "${expected_error}"
}

test_fails_if_2_with_args_argments_are_given() {
mock some-command --with-args "a" --with-args "b" > error
assert ${?} failed

assert "$(cat error)" equals "Cannot expect more than 1 set of argument for an invocation, please use 'mock' multiple times"
}
72 changes: 72 additions & 0 deletions test/test_mocking_multi_invocations.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/bin/bash

test_mocking_a_command_with_a_success_exit_code() {
mock some-command --and exit-code 0

some-command
assert ${?} succeeded
}

test_mocking_a_command_with_a_failure_exit_code() {
mock some-command --and exit-code 1

some-command
assert ${?} failed
}

test_mocking_a_command_to_return_a_value_and_exit_success() {
mock some-command --and echo "hello" --and exit-code 0

result=$(some-command)
assert ${?} succeeded

assert "${result}" equals "hello"
}

test_mocking_a_command_to_return_a_value_and_exit_failure() {
mock some-command --and echo "hello" --and exit-code 1

result=$(some-command)
assert ${?} failed

assert "${result}" equals "hello"
}

test_mocking_several_times_the_same_command() {
mock some-command --and exit-code 0
mock some-command --and exit-code 1
mock some-command --and exit-code 0

some-command
assert ${?} succeeded

some-command
assert ${?} failed

some-command
assert ${?} succeeded
}

test_no_mock_count_mocks_all_the_calls() {
mock some-command --and exit-code 0

some-command
assert ${?} succeeded

some-command
assert ${?} succeeded
}

test_mocking_a_second_time_assume_the_first_was_a_one_time_and_mocks_all_other_calls() {
mock some-command --and exit-code 1
mock some-command --and exit-code 0

some-command
assert ${?} failed

some-command
assert ${?} succeeded

some-command
assert ${?} succeeded
}

0 comments on commit bf6688c

Please sign in to comment.