pestphp/pest · error · DatasetMissing

The test [%s] in [%s] expects [%d] argument(s) ([%s]), but n

Error message

The test [%s] in [%s] expects [%d] argument(s) ([%s]), but no dataset was provided. Please chain [with()] onto the test to supply one.

What it means

If a test closure declares parameters and the test has no dataset, Pest cannot invoke it, so TestCaseFactory::addMethod throws DatasetMissing listing the file, description, and the expected argument names, with the hint to chain with(). Pest fails this at load time rather than letting every run crash with an ArgumentCountError.

Source

Thrown at src/Factories/TestCaseFactory.php:206

        }

        if (
            $method->closure instanceof \Closure &&
            new \ReflectionFunction($method->closure)->isStatic()
        ) {

            throw new TestClosureMustNotBeStatic($method);
        }

        if (! $method->receivesArguments()) {
            if (! $method->closure instanceof \Closure) {
                throw ShouldNotHappen::fromMessage('The test closure may not be empty.');
            }

            $arguments = Reflection::getFunctionArguments($method->closure);

            if ($arguments !== []) {
                throw new DatasetMissing($method->filename, $method->description, $arguments);
            }
        }

        $this->methods[$method->description] = $method;
    }

    public function hasMethod(string $methodName): bool
    {
        foreach ($this->methods as $method) {
            if ($method->description === null) {
                throw ShouldNotHappen::fromMessage('The test description may not be empty.');
            }

            if ($methodName === Str::evaluable($method->description)) {
                return true;
            }
        }

View on GitHub (pinned to 1af74a215c)

Solutions

  1. Chain a dataset: ->with([[1], [2]]) or ->with('datasets@case') for shared datasets in tests/Datasets.
  2. If the parameter can be optional, give it a default (function (int $n = 1)) — closures with only optional args don't require a dataset.
  3. If the parameter was a mistake, remove it from the closure signature.
  4. For expensive/DB-bound data use a lazy dataset: ->with(fn () => [...]).

Example fix

// before
it('formats money', function (int $cents) {
    expect(money($cents))->toBe('$1.00');
});
// after
it('formats money', function (int $cents) {
    expect(money($cents))->toBe('$1.00');
})->with([[100]]);
Defensive patterns

Strategy: validation

Validate before calling

// fail fast in helpers that register tests with parameters:
$required = (new ReflectionFunction($closure))->getNumberOfRequiredParameters();
if ($required > 0 && $dataset === null) {
    throw new LogicException("Test [{$description}] has {$required} required parameter(s) but no dataset");
}
$test = test($description, $closure);
if ($dataset !== null) {
    $test->with($dataset);
}

Prevention

When it happens

Trigger: it('works', function (int $n) { ... }); with no ->with(...) chained; deleting a dataset while keeping the parameter; adding a parameter for a future dataset and committing before wiring ->with(); helper wrappers that strip the ->with() chain.

Common situations: Mid-refactor commits where the signature changed first; converting PHPUnit @dataProvider tests and forgetting the with() half; tutorials' copy-paste that omit the dataset; dataset provided conditionally (only in some suites) so the error appears only in certain environments.

Related errors


AI-assisted analysis of pestphp/pest@1af74a215c (2026-08-21). Data as JSON: /api/errors/3bc169bb818c8211. Report an issue: GitHub.