Giter Club home page Giter Club logo

Comments (13)

dampcake avatar dampcake commented on August 23, 2024 3

One idea and what I have used in tests is to create a function that overrides the actual executable. Something like:

@test "my override test" {
  mock_curl="$(mock_create)"
  curl() {
    "${mock_curl}" "$@"
  }
  run something_that_call_curl
  [ "$(mock_get_call_num "${mock_curl}")" -eq 1 ]
}

In fact I had been using just regular functions to do all my mocking for quite a while until I ran into issues of not being able to get call counts or easily access multiple calls arguments.

from bats-mock.

dragon788 avatar dragon788 commented on August 23, 2024

Upon reflecting on this I also realized that you need to use an additional $(create_mock) call for each binary you want to stub, otherwise you won't be tracking the right number of calls and args, so making a helper function like what jasonkarns/bats-mock uses for stub is probably the way to go.

from bats-mock.

grayhemp avatar grayhemp commented on August 23, 2024

@dragon788 thanks very much for your feedback. I was thinking about possibilities of mocking executables by their real names myself. And yes, symlink-ing + PATH manipulations occurred to me as well. However, the issue with this approach is that the executable can be specified with a path component (like /usr/local/bin/psql) in the script and so the idea breaks here. Not speaking about possible PATH manipulations by the script itself.

I have a hint of idea of solving that by chroot-ing into a disposable tree and doing unsafe things there but nothing is clear here yet, so I'm not sure if it's going to be the solution or there will be something else. I was a little bit hesitant about this enhancement, but after your message I started seeing a clear demand in it, so I scheduled work on it in terms of v2.0.

from bats-mock.

dragon788 avatar dragon788 commented on August 23, 2024

Was interesting checking the implementation of stub.sh after discovering it in the question referenced above. https://github.com/jimeh/stub.sh/blob/master/stub.sh Haven't fully digested whether it can handle full paths and still stub the binary or not.

from bats-mock.

grayhemp avatar grayhemp commented on August 23, 2024

@dragon788 interesting tool, thank you. However, I'm a little bit afraid of stub/restore approaches. From my previous experience it's an easy way to shoot oneself in the foot.

from bats-mock.

dragon788 avatar dragon788 commented on August 23, 2024

I definitely think your idea of doing it in a chroot is the safest route, that way it can be destroyed between tests to prevent side effects and can't alter the host and cause any issues.

from bats-mock.

pszalko avatar pszalko commented on August 23, 2024

I just found this bat-mock tool and it looks very promising for unit testing bash code. I wonder if there is any progress with this issue?

from bats-mock.

grayhemp avatar grayhemp commented on August 23, 2024

@pszalko unfortunately it appeared to be harder that though and I just don't have enough time currently to address it properly. However, I would highly appreciate any PRs and/or ideas.

from bats-mock.

cescp avatar cescp commented on August 23, 2024

Solution from @dampcake is not working for me. It seems that function defined in @test is not passed to run: my script, which calls curl, takes it from system instead of mock.

To verify it, use another non-existing command (e.g. carl):
myscript.sh:

#!/usr/bin/env bash

carl --help

exit 0

and test:

@test "test mocked curl" {
    mock_curl="$(mock_create)"
    carl() {
	"${mock_curl}" "$@"
    }

    run myscript.sh
    [ "$(mock_get_call_num "${mock_curl}")" -eq 1 ]
}

When running test I get:

myscript.sh: line 3: carl: command not found

from bats-mock.

espoelstra avatar espoelstra commented on August 23, 2024

Did you create the carl script in a folder that is present in the PATH variable? Some distributions include the current directory (.) in the PATH, that has become less common since it can be a security issue, it is better to temporarily replace or extend the PATH variable explicitly for your test execution.

from bats-mock.

cescp avatar cescp commented on August 23, 2024

This is the complete example with curl. Both files are in the same dir.
myscript.sh:

#!/usr/bin/env bash

curl

exit 0

test.bats:

#!/usr/bin/env bats

setup() {
    # https://bats-core.readthedocs.io/en/stable/
    
    # modules installed with nvm and global npm:
    # npm install -g bats-support
    # npm install -g bats-assert
    load ${NVM_BIN}/../lib/node_modules/bats-support/load.bash
    load ${NVM_BIN}/../lib/node_modules/bats-assert/load.bash

    # module installed with:
    # https://github.com/grayhemp/bats-mock#installation
    # ./build install
    load /usr/local/lib/bats-mock.bash

    # get the containing directory of this file
    # use $BATS_TEST_FILENAME instead of ${BASH_SOURCE[0]} or $0,
    # as those will point to the bats executable's location or the preprocessed file respectively
    DIR="$( cd "$( dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )"
    # make executables in . visible to PATH
    PATH="$DIR:$PATH"
}


@test "test mocked curl" {
    mock_curl="$(mock_create)"
    mock_set_output ${mock_curl} "this is the output from mock"
    curl() {
	"${mock_curl}" "$@"
    }

    # run something_that_call_curl
    echo "-- running myscript.sh" >&3
    run myscript.sh
    echo "${output}" >&3
    # this check will fail
    #[ "$(mock_get_call_num "${mock_curl}")" -eq 1 ]

    # run local function
    echo "-- running local function" >&3
    run curl
    echo "${output}" >&3
    # this check will succeed
    [ "$(mock_get_call_num "${mock_curl}")" -eq 1 ]
}

Myscript is not seeing the mocked version of curl, but the system real version of it. As expected, direct run of curl function from test.bats is working fine:

$ bats test.bats
✓ test mocked curl
-- running myscript.sh
curl: try 'curl --help' or 'curl --manual' for more information
-- running local function
this is the output from mock

1 test, 0 failures

from bats-mock.

jkenlooper avatar jkenlooper commented on August 23, 2024

Would using a symlink to the mocked version of curl and prepending it to the PATH inside the test work?

@test "test mocked curl" {
  mock_curl="$(mock_create)"
  mock_set_output ${mock_curl} "this is the output from mock"

  ln -s "${mock_curl}" $BATS_RUN_TMPDIR/curl
  PATH="$BATS_RUN_TMPDIR:$PATH"

  # run something_that_call_curl
  echo "-- running myscript.sh" >&3
  run myscript.sh
  echo "${output}" >&3
  # this check should pass now
  [ "$(mock_get_call_num "${mock_curl}")" -eq 1 ]

  # run local function
  echo "-- running local function" >&3
  run curl
  echo "${output}" >&3
  # this check will succeed

}

from bats-mock.

mh182 avatar mh182 commented on August 23, 2024

PR #20 contains a tentative implementation (and would also solve #17).

It doesn't use chown but it is good enough for my test setup.

Restriction to PR #20: it doesn't work for testing shell scripts with hard-coded absolute paths.

from bats-mock.

Related Issues (11)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.