R mock测试修改锁定命名空间函数在R CMD check下报错解决方案问询
错误原因
R CMD check 运行时会自动锁定所有第三方依赖包的命名空间绑定,避免测试代码随意修改外部包函数带来的不可预期问题。你用的mockthat、mockery等工具的默认mock逻辑是直接修改目标函数所在环境的绑定,自然就会触发「无法修改锁定绑定」的报错。而devtools::test()运行时没有开启命名空间锁定检查,所以可以正常执行。
解决方案1:给外部函数加自实现包装层(改动最小)
你只需要在自己的包代码中,给需要调用的RCurl::getURL加一层内部包装函数,mock的时候改为mock你自己的包装函数即可,你的包内部的函数绑定不会被R CMD check锁定。
- 包业务代码修改示例:
# 放在你包的R代码文件里,作为内部函数 .my_get_url <- function(url, ...) { RCurl::getURL(url, ...) } # 原来的myFunction中所有调用getURL的位置,替换为调用.my_get_url myFunction <- function() { # ...其他逻辑 res <- .my_get_url("https://target-api.com/xxx") # ...其他逻辑 }
- 修改后的测试代码:
library(mockthat) test_that("API works", { mock_response <- mockthat::mock('[{"foo":7}]') mockthat::with_mock( # 将mypkg替换为你自己的包名,三个冒号表示访问包内部函数 mypkg:::.my_get_url = mock_response, { result <- myFunction() } ) # 此处添加你的断言逻辑 })
解决方案2:使用HTTP请求拦截工具(无需修改业务代码)
如果不想改动业务代码,可以选用专门用于mock网络请求的webmockr包,它的实现逻辑是直接拦截HTTP请求返回预设值,不需要修改任何函数绑定,完全避开锁定绑定的问题。
测试代码示例:
library(webmockr) library(testthat) # 开启RCurl请求的拦截 webmockr::enable(adapter = "rcurl") test_that("API works", { # 预设目标请求的返回值,将URL替换为你实际请求的地址 stub_request("get", "https://your-target-api-url.com/path") %>% to_return(status = 200, body = '[{"foo":7}]', headers = list('Content-Type' = 'application/json')) # 直接调用原函数即可,不需要额外修改 result <- myFunction() # 可选:验证请求是否符合预期 expect_requested("get", "https://your-target-api-url.com/path", times = 1) # 此处添加你的断言逻辑 }) # 测试完成后关闭拦截 webmockr::disable(adapter = "rcurl")
内容的提问来源于stack exchange,提问作者Ken Williams
相关产品推荐
相关产品推荐

