Testing Code With External Dependencies.

2 min read

A stub is a controllable replacement of a dependency in your system.

Stubbing helps you test your code without directly interacting with a dependency, e.g., an API.

How to test the_ultimate_question_of function if the_answer:

#' R/the_ultimate_question_of.R
the_ultimate_question_of <- function(
  x = c("Life", "Universe", "Everything")
) {
  x <- match.arg(x)
  the_answer(x)
}

Let’s write our first test.

#' tests/testthat/test-the_ultimate_question_of.R
test_that("the_ultimate_question_of returns 42", {
  # Arrange
  input <- "Everything"

  # Act
  result <- the_ultimate_question_of(input)

  # Assert
  expect_equal(result, ???)
})

We need to stub the the_answer.

We can use testthat::local_mocked_bindings.

#' tests/testthat/test-the_ultimate_question_of.R
test_that("the_ultimate_question_of returns 42", {
  # Arrange
  local_mocked_bindings(the_answer = function(x) 42)
  input <- "Everything"

  # Act
  result <- the_ultimate_question_of(input)

  # Assert
  expect_equal(result, ???)
})

Then we can assert that the answer to "Everything" is 42.

#' tests/testthat/test-the_ultimate_question_of.R
test_that("the_ultimate_question_of returns 42", {
  # Arrange
  local_mocked_bindings(
    the_answer = function(x) 42
  )

  input <- "Everything"

  # Act
  result <- the_ultimate_question_of(input)

  # Assert
  expect_equal(result, 42)
})

Before {testthat} version 3.2.0, mockery::stub had to be used.

#' tests/testthat/test-my_function.R
test_that("the_ultimate_question_of returns 42", {
  # Arrange
  mockery::stub(
    where = the_ultimate_question_of,
    what = "the_answer",
    how = 42
  )
  input <- "Everything"

  # Act
  result <- the_ultimate_question_of(input)

  # Assert
  expect_equal(result, 42)
})

So testthat::local_mocked_bindings:

testthat::local_mocked_bindings let’s you quickly start with stubbing in your tests.

For more advanced use cases you still need to rely on {mockery}.