PHPackages                             sophie-spec/throws - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. sophie-spec/throws

ActiveLibrary[Testing &amp; Quality](/categories/testing)

sophie-spec/throws
==================

Verify thrown exceptions from a callable

0.1.4(4y ago)023MITPHPPHP &gt;=7.4.0

Since Mar 28Pushed 4y ago1 watchersCompare

[ Source](https://github.com/SophieSpec/throws)[ Packagist](https://packagist.org/packages/sophie-spec/throws)[ RSS](/packages/sophie-spec-throws/feed)WikiDiscussions master Synced 1w ago

READMEChangelogDependencies (12)Versions (6)Used By (0)

Throws
======

[](#throws)

It is a unit test tool to verify if a callable throws (or not) an exception.

Install
-------

[](#install)

```
composer require --dev sophie-spec/throws
```

Requires PHP &gt;= 7.4.

Use
---

[](#use)

Depending on the context, `throws()` and `throws_not()` can throw `ShouldHaveThrownException` or `ShouldHaveNotThrownException`.

```
$legal_age = function ($age) {
    if ($age < 18) {
        throw new UnderLegalAgeException("Not a legal age");
    }
};

// It does not throw an exception since
// $legal_age throws an exception, as expected.
throws(fn() => $legal_age(5));

// Here, it throws a ShouldHaveThrownException.
throws(fn() => $legal_age(20));

// We can specify what exception we're expecting:
// since we tell to throws() to catch UnderLegalAgeException exceptions
// it won't throw an exception itself.
throws(fn() => $legal_age(5), UnderLegalAgeException::class);

// Of course, we can tell it to catch Exception exceptions,
// and it would catch UnderLegalAgeException as expected.
throws(fn() => $legal_age(5), Exception::class);

// Here, it would throw a ShouldHaveNotThrownException
// because we're catching SomeOtherException and nothing more.
throws(fn() => $legal_age(5), SomeOtherException::class);

// And, of course, you can catch several exception types.
throws(
    fn() => $legal_age(5),
    SomeOtherException::class,
    UnderLegalAgeException::class
);

// Here's the opposite of throws(), in this example
// it throws a ShouldHaveNotThrownException.
throws_not(fn() => $legal_age(5));

// Yay! $legal_age(20) does not throw an exception!
throws_not(fn() => $legal_age(20));

// Like throws(), we can specify some exception classes to not catch.
// Here, $legal_age(5) still throws an exception and since we're just
// verifying that it does not throw an InvalidArgumentException, so
// throws_not() does not throw a ShouldHaveNotThrownException.
throws_not(fn() => $legal_age(5), InvalidArgumentException::class);

// Now, it throws a ShouldHaveNotThrownException.
throws_not(fn() => $legal_age(5), UnderLegalAgeException::class);
```

**Please note, and it's very important, that `throws_not()` can lead to false positives. When you're trying to catch a specific exception, if another exception occurs it will be shut. Then, be sure to know what you're doing when using specific exceptions catching with `throws_not()`!**

License
-------

[](#license)

[MIT](http://dreamysource.mit-license.org).

###  Health Score

23

—

LowBetter than 27% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~169 days

Total

5

Last Release

1564d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/cfa0184a566f6328ade4c85c55bf01044302437b66214a710880e5387f015831?d=identicon)[sophie-spec](/maintainers/sophie-spec)

---

Top Contributors

[![pyrsmk](https://avatars.githubusercontent.com/u/214497?v=4)](https://github.com/pyrsmk "pyrsmk (5 commits)")

---

Tags

phpunitunittestcoverageassertXdebugspecphpspecatoumrspecsophie

###  Code Quality

Static AnalysisPsalm

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/sophie-spec-throws/health.svg)

```
[![Health](https://phpackages.com/badges/sophie-spec-throws/health.svg)](https://phpackages.com/packages/sophie-spec-throws)
```

###  Alternatives

[nette/tester

Nette Tester: enjoyable unit testing in PHP with code coverage reporter. 🍏🍏🍎🍏

4917.3M1.5k](/packages/nette-tester)[friends-of-phpspec/phpspec-code-coverage

Generate Code Coverage reports for PhpSpec tests

202.6M125](/packages/friends-of-phpspec-phpspec-code-coverage)[elliotchance/concise

Concise is test framework for using plain English and minimal code, built on PHPUnit.

45223.8k4](/packages/elliotchance-concise)[colinodell/psr-testlogger

PSR-3 compliant test logger based on psr/log v1's, but compatible with v2 and v3 too!

1712.1M47](/packages/colinodell-psr-testlogger)[diablomedia/phpunit-pretty-printer

A PHPUnit result printer that shows per-file test progress and execution times

78515.2k5](/packages/diablomedia-phpunit-pretty-printer)[icecave/isolator

Dependency injection for global functions.

371.3M29](/packages/icecave-isolator)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
