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