0

I have set up a R Shiny app using the golem R-package. In the app_server() I use some globally set golem options as follows:

app_server <- function(input, output, session) {

  myServer(
    id = "test",
    global_variable = golem::get_golem_options()$global_variable,
    other_variable = other_variable
  )

  ...

}

Now the default test testServer() in test-golem-recommended.R throws an error because within myServer() it can't find the golem options or the global_variable is NULL (which also kind of makes sense):

testServer(app_server, {

  # Set and test an input
  session$setInputs(x = 2)
  expect_equal(input$x, 2)

})

However, is it possible to call app_server() so that the golem options are loaded first?

moremo
  • 315
  • 2
  • 11

1 Answers1

1

I encountered the same issue, and have an inelegant solution that involves setting the golem_options explicitly during the unit testing phase.

First, I defined a function to set the golem_options. This can be anywhere in your package, or defined in the testthat script:

#' Set golem options for unit testing purposes
#'
#' @param golem_opts list()
#'
#' @examples
#' \dontrun{
#'   my_golem_options <-
#'   list(
#'     myconfig = "config01"
#'   )
#'   set_testing_golem_options(my_golem_options)
#' }
set_testing_golem_options <-
  function (golem_opts)
  {
    current_golem_options = getShinyOption("golem_options")
    for (n in names(golem_opts)) {
      current_golem_options[[n]] <- golem_opts[[n]]
    }
    shinyOptions(golem_options = current_golem_options)
  }

Then you want to do 3 things just before the testServer action in the test-golem-recommended.R:

  1. Set your golem_options:
set_testing_golem_options(list(global_variable = 'somevalue'))
  • Alternatively, you could just make a list of options without the function listed above, but the function will respect any other shinyOptions that happen to be already set.
  1. Explicitly define the MockShinySession that you're going to use for testing:
defined_mock_shiny_session <- MockShinySession$new()
  1. Assign the options into the mock session:
defined_mock_shiny_session$options[['golem_options']] <-
  getShinyOption("golem_options")
  1. Now the trick is to call the testServer with the explicit MockShinySession that you've just created:
testServer(
  app_server, 
  {

    # Set and test an input
    session$setInputs(x = 2)
    expect_equal(input$x, 2)
  },
  session = defined_mock_shiny_session
)

That pattern works for me. I should probably explicitly unset any golem_options after the test is complete, or ensure that they revert back to their previous state in some way. But hopefully this will get you unstuck.

Here's everything all in one code block using the example you provided:

# Define the function to set golem_options
set_testing_golem_options <-
  function (golem_opts)
  {
    current_golem_options = getShinyOption("golem_options")
    for (n in names(golem_opts)) {
      current_golem_options[[n]] <- golem_opts[[n]]
    }
    shinyOptions(golem_options = current_golem_options)
  }

# Set the golem_options that you need
set_testing_golem_options(list(global_variable = 'somevalue'))

# Create the mock session
defined_mock_shiny_session <- MockShinySession$new()

# Assign the golem_options
defined_mock_shiny_session$options[['golem_options']] <-
  getShinyOption("golem_options")

# Execute the test
testServer(
  app_server, 
  {

    # Set and test an input
    session$setInputs(x = 2)
    expect_equal(input$x, 2)

  },
  session = defined_mock_shiny_session
)