1 2#' Expectation: does the given call match the expected? 3#' 4#' Together with \code{\link{mock}} can be used to verify whether the 5#' call expression (\code{\link{expect_call}}) and/or argument values 6#' (\code{\link{expect_args}}) match the expected. 7#' 8#' With \code{expect_called} you can check how many times has the mock 9#' object been called. 10#' 11#' @param mock_object A \code{\link{mock}} object. 12#' @param n Call number or total number of calls. 13#' @param expected_call Expected call expression; will be compared unevaluated. 14#' @param ... Arguments as passed in a call. 15#' 16#' @examples 17#' library(testthat) 18#' 19#' # expect call expression (signature) 20#' m <- mock() 21#' with_mock(summary = m, summary(iris)) 22#' 23#' # it has been called once 24#' expect_called(m, 1) 25#' 26#' # the first (and only) call's arguments matches summary(iris) 27#' expect_call(m, 1, summary(iris)) 28#' 29#' # expect argument value 30#' m <- mock() 31#' a <- iris 32#' with_mock(summary = m, summary(object = a)) 33#' expect_args(m, 1, object = a) 34#' # is an equivalent to ... 35#' expect_equal(mock_args(m)[[1]], list(object = a)) 36#' 37#' @name call-expectations 38#' 39NULL 40 41 42 43#' @export 44#' @rdname call-expectations 45#' 46#' @importFrom testthat expect 47expect_call <- function (mock_object, n, expected_call) { 48 stopifnot(is_mock(mock_object)) 49 50 expect( 51 0 < n && n <= length(mock_object), 52 sprintf("call number %s not found in mock object", toString(n)) 53 ) 54 55 expected_call <- substitute(expected_call) 56 mocked_call <- mock_calls(mock_object)[[n]] 57 58 format_call <- function (x) paste(trimws(deparse(x)), collapse = ' ') 59 60 expect( 61 identical(mocked_call, expected_call), 62 sprintf("expected call %s does not mach actual call %s.", 63 format_call(expected_call), format_call(mocked_call)) 64 ) 65 66 invisible(TRUE) 67} 68 69 70#' @export 71#' @rdname call-expectations 72#' 73#' @importFrom testthat expect expect_equal 74expect_args <- function (mock_object, n, ...) 75{ 76 stopifnot(is_mock(mock_object)) 77 78 expect( 79 0 < n && n <= length(mock_object), 80 sprintf("arguments list number %s not found in mock object", toString(n)) 81 ) 82 83 expected_args <- list(...) 84 actual_args <- mock_args(mock_object)[[n]] 85 86 expect_equal(length(actual_args), length(expected_args), 87 info = 'number of expected args does not match the actual') 88 89 for (i in seq_along(actual_args)) { 90 expect_equal( 91 actual_args[[i]], 92 expected_args[[i]], 93 label = paste(ordinal(i), 'actual argument'), 94 expected.label = paste(ordinal(i), 'expected argument') 95 ) 96 } 97 98 invisible(TRUE) 99} 100 101 102ordinal <- function (x) 103{ 104 stopifnot(is.integer(x), x > 0, length(x) == 1) 105 if (x %in% 11:13) 106 return(paste0(x, 'th')) 107 108 as_string <- as.character(x) 109 last_digit <- substring(as_string, nchar(as_string)) 110 suffix <- switch(last_digit, 111 `1` = 'st', 112 `2` = 'nd', 113 `3` = 'rd', 114 'th') 115 paste0(as_string, suffix) 116} 117 118 119#' @export 120#' @rdname call-expectations 121expect_called <- function (mock_object, n) 122{ 123 stopifnot(is_mock(mock_object)) 124 125 expect( 126 length(mock_object) == n, 127 sprintf("mock object has not been called %s time%s", toString(n), 128 (if(n>1) "s" else "")) 129 ) 130} 131