grayhemp / bats-mock Goto Github PK
View Code? Open in Web Editor NEWMocking for Bats
License: The Unlicense
Mocking for Bats
License: The Unlicense
I think things are pretty stable now. How about tagging and releasing v1.0.0?
When running the bats-mock tests, two of the mock_create tests fail:
not ok 1 mock_create creates a program
# (in test file test/mock_create.bats, line 12)
# `[[ -x "${output}" ]]' failed
ok 2 mock_create names the program uniquely
not ok 3 mock_create creates a program in BATS_TMPDIR
# (in test file test/mock_create.bats, line 27)
# `[[ "$(dirname ${output})" = "${BATS_TMPDIR}" ]]' failed
...
Experimentation has found that if TMPDIR is set to a directory without any inaccessible directories, e.g.:
TMPDIR=`mktemp -d` ./build test
Then the tests pass:
ok 1 mock_create creates a program
ok 2 mock_create names the program uniquely
ok 3 mock_create creates a program in BATS_TMPDIR
...
The problem occurs when TMPDIR
is unset (and thus /tmp
is used) or if TMPDIR
is set, and in either case the directory to which it refers contains directories that find
cannot access.
The bats modules at https://github.com/bats-core all follow the convention to provide a load.bash
file in the module root directory that sources all required bash files.
While bats-mock comes as a single file module, it would still be beneficial to be able to use the same convention as for the other modules. It would also allow bats-mock to grow without introducing breaking changes (there will always be just a single load.bash
file).
I love the syntax of your implementation and it makes a lot of sense to me that the mock is a test double/spy that watches all the invocations and allows you to assert that it was called in specific ways, without necessarily having to write out an assertion for every single call.
While trolling StackOverflow and related sites I came across a question about mocking a script and checking the calls using bats-mock
, but they were using the other version and it doesn't make it quite as easy to assert mock_called_with_args
or similar, so I wrote up an answer with an example using your bats-mock, but I was having trouble emulating the stub
behavior of actually shadowing/preempting a binary in the PATH so that the ${mock}
definition was called instead. https://stackoverflow.com/q/38315185/3794873
I eventually came up with a hacky method by doing the mock creation in the setup()
method or in each test and then by making a symlink to the mock's file path in the same directory and prepending that directory to the PATH variable and then unlinking and stripping the location back out of the PATH in the teardown or the end of the test. Is there a cleaner way to do this without repeating the code across all of the tests and in such a way that it allows for one or more binaries to be stubbed, in the case you want to avoid any external resources being accessed and you could stub success for the list?
Perhaps this is something that could be added to this better maintained version of bats-mock? Maybe something like mock_set_command_stub_name
.
Hey,
first of all: thanks for providing this library - it simplifies script testing a lot!
I tried the TDD approach in a script-heavy project and found it quite hard to test piped commands:
...
envsubst < "${ARG_SOURCE_PATH}/shared/kind/kind.yaml" | kind create cluster --config -
...
In this example i pipe a yaml config file to the kind command.
When mocking the kind command it is possible to get the args with mock_get_call_args
, but is there a possibility to get the piped config value (stdin) too?
Maybe we could capture stdin in your generated mock file and provide a function mock_get_call_stdin
- what do u think?
Hi,
I'm trying to mock a function that another function calls. In my test, I then want to verify the output of the non-mocked function. Here is an example of what I'm trying to do (the output of function two is based on the mocked property of my_special_func
.
mocked_command="my_special_func"
mock="$(mock_create)"
mock_set_property "${mock}" STATUS 400
"${mock}" run function_two ARG1 ARG2
assert_equal "expected_value" "function_two_output"
Do you have any suggestions on how to do this?
Thanks very much!
Anna
Is it possible to add a mock to path? I have a script that calls i.e. the Linux ip
command, I want to track that everything works as expected.
For that I'd create a mock, call it ip
and prepend it to the PATH variable. Is this somehow already possible?
bats-mock fails if optional arguments to getter or setter functions are omitted and the expansion of unset variables / parameters is not allowed (that is, when set -u
is used).
Some people are using set -euo pipefail
in scripts to enforce a clean coding style. Sourcing such a script for testing may break tests using bats-mock.
How to reproduce:
#!/usr/bin/env bats
load bats-mock/src/bats-mock
setup() {
mock="$(mock_create)"
"${mock}"
}
@test "mock_get_call_args() with omitted optional argument succeeds when expansion of unset arguments is allowed" {
set +u
run mock_get_call_args "${mock}"
[[ "${status}" -eq 0 ]]
}
@test "mock_get_call_args() with omitted optional argument fails with unbound variable error when expansion of unset arguments is not allowed" {
set -u
run mock_get_call_args "${mock}"
[[ "${status}" -ne 0 ]]
[[ "${output}" =~ '/bats-mock.bash: line '[0-9]*': $2: unbound variable' ]]
}
Workaround:
Instead of
[[ "$(mock_get_call_args "${mock}")" -ne 0 ]]
use
[[ "$(set +u; mock_get_call_args "${mock}")" -ne 0 ]]
Possible Solution:
Use ${2-}
instead of $2
(provided $2
is optional).
Example (from mock_get_call_args
):
n="$(mock_default_n ${mock} ${2-})" || exit "$?"
Great library, thanks!
I was wondering if you would consider publishing it to npm, as the other bats support libraries (like bats-assert and bats-support) are already there.
Thanks!
Given:
@test "my test" {
my_mock="$(mock_create)"
"${my_mock}" -n -e arguments
[ "$(mock_get_call_args "${my_mock}")" = "-n -e arguments" ]
}
I would expect this to work. Unfortunately the arguments captured are just arguments
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.