Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cannot change value of locked binding #6

Open
kenahoo opened this issue Sep 24, 2021 · 6 comments
Open

cannot change value of locked binding #6

kenahoo opened this issue Sep 24, 2021 · 6 comments

Comments

@kenahoo
Copy link

kenahoo commented Sep 24, 2021

I've got a package that I'm testing, and I call getURL from the RCurl package in it. That function is imported, so my NAMESPACE has importFrom(RCurl,getURL) in it.

When I mock that out in my testing, I do this:

library(mockthat)

test_that("API works", {

  response <- data.frame(foo = 7)
  mock_response <- mockthat::mock(as.character(jsonlite::toJSON(response)))

  mockthat::with_mock(
    getURL=mock_response,
    {
      result <- myFunction()
    })

This fails with the following error, but only when I run under devtools::check() (it succeeds under devtools::test()):

not ok 1 API works
  Error: cannot change value of locked binding for 'getURL'
  Backtrace:
   1. mockthat::with_mock(...) test-yes.R:29:2
   2. base::lapply(mocks, set_mock)
   3. mockthat:::FUN(X[[i]], ...)
   4. mockthat:::do_assign(mock$name, mock$new_value, mock$env)
   5. base::assign(name, val, envir = env)
not ok 2 API works
  Error: cannot change value of locked binding for 'getURL'
  Backtrace:
   1. mockthat::with_mock(...) test-yes.R:29:2
   2. base::lapply(mocks, reset_mock) test-yes.R:29:2
   3. mockthat:::FUN(X[[i]], ...)
   4. mockthat:::do_assign(mock$name, mock$orig_value, mock$env)
   5. base::assign(name, val, envir = env)

Is there something I need to do differently for an imported function like this?

I'm using:

> packageVersion('mockthat')
[1] '0.2.6'

> cat(head(capture.output(sessionInfo()), 3), sep="\n")
R version 4.1.1 (2021-08-10)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Big Sur 11.4

Apologies for not creating a proper reprex - it will take quite a while to slim down my package code to something isolated, and I'm also not sure how to demonstrate the problem without having a whole package structure.

@kenahoo
Copy link
Author

kenahoo commented Sep 27, 2021

I have also tried unlocking the environment during testing a few different ways, but haven't found anything that works:

unlockBinding("getURL", env=.getNamespace("RCurl"))
unlockBinding("getURL", env=.BaseNamespaceEnv)
unlockBinding("getURL", env=.getNamespace("mypackage"))

@kenahoo
Copy link
Author

kenahoo commented Jan 7, 2022

Hi @nbenn , have you had a chance to think about this? I'm also hitting it when I try to mock s3write_using from the aws.s3 package.

  Error in `assign(name, val, envir = env)`: cannot change value of locked binding for 's3write_using'
  Backtrace:
   1. mockthat::with_mock(...) test-io.r:15:2
   2. base::lapply(mocks, set_mock)
   3. mockthat:::FUN(X[[i]], ...)
   4. mockthat:::do_assign(mock$name, mock$new_value, mock$env)
   5. base::assign(name, val, envir = env)

nbenn added a commit to nbenn/mockthat6 that referenced this issue Jan 9, 2022
@nbenn
Copy link
Owner

nbenn commented Jan 9, 2022

I'm very sorry for not having gotten back to you earlier! I tried to reproduce your issue (see nbenn/mockthat6) and I pushed a small fix that resolves the issue in that particular instance. Let me know if you're still having troubles and feel free to submit a PR to the mockthat6 repo if this does not yet cover your use-case. Let me know if your problem is solved, so that I can send an update to CRAN.

@kenahoo
Copy link
Author

kenahoo commented Jan 13, 2022

Thanks @nbenn - don't worry about the lag! I know attention is a precious resource.

I think this fix does the trick. I can now import functions like so

#' @importFrom aws.s3 s3write_using
#' @importFrom withr local_envvar

in my package code, and then do

mockthat::with_mock(
    s3write_using=mock_s3,
    local_envvar=mock_envvar,
    ...)

in my testing code, and it seems to work under both devtools::check() and devtools::test(). Thanks!

@kenahoo
Copy link
Author

kenahoo commented Apr 21, 2022

Hi @nbenn - any chance you can release a version to CRAN with this fix?

@kenahoo
Copy link
Author

kenahoo commented Mar 20, 2023

Looks like version 0.2.8, released 2022-11-01, includes this fix, so this ticket can be closed. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants