diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 07de108..65f351a 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -101,6 +101,7 @@ jobs:
           - "^9.5"
           - "^10.5"
           - "^11.5"
+          - "^12.0.9"
         exclude:
           - php-version: "7.4"
             phpunit-version: "^10.5"
@@ -112,6 +113,14 @@ jobs:
             phpunit-version: "^11.5"
           - php-version: "8.1"
             phpunit-version: "^11.5"
+          - php-version: "7.4"
+            phpunit-version: "^12.0.9"
+          - php-version: "8.0"
+            phpunit-version: "^12.0.9"
+          - php-version: "8.1"
+            phpunit-version: "^12.0.9"
+          - php-version: "8.2"
+            phpunit-version: "^12.0.9"
 
     steps:
       - name: "Checkout"
@@ -158,6 +167,7 @@ jobs:
           - "^9.5"
           - "^10.5"
           - "^11.5"
+          - "^12.0.9"
         exclude:
           - php-version: "7.4"
             phpunit-version: "^10.5"
@@ -169,6 +179,14 @@ jobs:
             phpunit-version: "^11.5"
           - php-version: "8.1"
             phpunit-version: "^11.5"
+          - php-version: "7.4"
+            phpunit-version: "^12.0.9"
+          - php-version: "8.0"
+            phpunit-version: "^12.0.9"
+          - php-version: "8.1"
+            phpunit-version: "^12.0.9"
+          - php-version: "8.2"
+            phpunit-version: "^12.0.9"
 
     steps:
       - name: "Checkout"
diff --git a/extension.neon b/extension.neon
index 8de21f5..117c992 100644
--- a/extension.neon
+++ b/extension.neon
@@ -12,7 +12,6 @@ parameters:
 		- stubs/Assert.stub
 		- stubs/AssertionFailedError.stub
 		- stubs/ExpectationFailedException.stub
-		- stubs/InvocationMocker.stub
 		- stubs/MockBuilder.stub
 		- stubs/MockObject.stub
 		- stubs/Stub.stub
@@ -42,18 +41,10 @@ services:
 		class: PHPStan\Type\PHPUnit\Assert\AssertStaticMethodTypeSpecifyingExtension
 		tags:
 			- phpstan.typeSpecifier.staticMethodTypeSpecifyingExtension
-	-
-		class: PHPStan\Type\PHPUnit\InvocationMockerDynamicReturnTypeExtension
-		tags:
-			- phpstan.broker.dynamicMethodReturnTypeExtension
 	-
 		class: PHPStan\Type\PHPUnit\MockBuilderDynamicReturnTypeExtension
 		tags:
 			- phpstan.broker.dynamicMethodReturnTypeExtension
-	-
-		class: PHPStan\Type\PHPUnit\MockObjectDynamicReturnTypeExtension
-		tags:
-			- phpstan.broker.dynamicMethodReturnTypeExtension
 	-
 		class: PHPStan\Rules\PHPUnit\CoversHelper
 	-
diff --git a/phpstan.neon b/phpstan.neon
index 7c96296..5737945 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -9,3 +9,8 @@ includes:
 parameters:
 	excludePaths:
 		- tests/*/data/*
+	ignoreErrors:
+		-
+			message: '#^Attribute class PHPUnit\\Framework\\Attributes\\DataProvider does not exist\.$#'
+			identifier: attribute.notFound
+			reportUnmatched: false
diff --git a/src/Rules/PHPUnit/MockMethodCallRule.php b/src/Rules/PHPUnit/MockMethodCallRule.php
index b6f8932..e953d18 100644
--- a/src/Rules/PHPUnit/MockMethodCallRule.php
+++ b/src/Rules/PHPUnit/MockMethodCallRule.php
@@ -5,9 +5,10 @@
 use PhpParser\Node;
 use PhpParser\Node\Expr\MethodCall;
 use PHPStan\Analyser\Scope;
+use PHPStan\Rules\IdentifierRuleError;
 use PHPStan\Rules\Rule;
 use PHPStan\Rules\RuleErrorBuilder;
-use PHPUnit\Framework\MockObject\Builder\InvocationMocker;
+use PHPStan\Type\Type;
 use PHPUnit\Framework\MockObject\MockObject;
 use PHPUnit\Framework\MockObject\Stub;
 use function array_filter;
@@ -47,44 +48,58 @@ public function processNode(Node $node, Scope $scope): array
 			$method = $constantString->getValue();
 			$type = $scope->getType($node->var);
 
-			if (
-				(
-					in_array(MockObject::class, $type->getObjectClassNames(), true)
-					|| in_array(Stub::class, $type->getObjectClassNames(), true)
-				)
-				&& !$type->hasMethod($method)->yes()
-			) {
-				$mockClasses = array_filter($type->getObjectClassNames(), static fn (string $class): bool => $class !== MockObject::class && $class !== Stub::class);
-				if (count($mockClasses) === 0) {
-					continue;
-				}
-
-				$errors[] = RuleErrorBuilder::message(sprintf(
-					'Trying to mock an undefined method %s() on class %s.',
-					$method,
-					implode('&', $mockClasses),
-				))->identifier('phpunit.mockMethod')->build();
+			$error = $this->checkCallOnType($type, $method);
+			if ($error !== null) {
+				$errors[] = $error;
 				continue;
 			}
 
-			$mockedClassObject = $type->getTemplateType(InvocationMocker::class, 'TMockedClass');
-			if ($mockedClassObject->hasMethod($method)->yes()) {
+			if (!$node->var instanceof MethodCall) {
 				continue;
 			}
 
-			$classNames = $mockedClassObject->getObjectClassNames();
-			if (count($classNames) === 0) {
+			if (!$node->var->name instanceof Node\Identifier) {
 				continue;
 			}
 
-			$errors[] = RuleErrorBuilder::message(sprintf(
+			if ($node->var->name->toLowerString() !== 'expects') {
+				continue;
+			}
+
+			$varType = $scope->getType($node->var->var);
+			$error = $this->checkCallOnType($varType, $method);
+			if ($error === null) {
+				continue;
+			}
+
+			$errors[] = $error;
+		}
+
+		return $errors;
+	}
+
+	private function checkCallOnType(Type $type, string $method): ?IdentifierRuleError
+	{
+		if (
+			(
+				in_array(MockObject::class, $type->getObjectClassNames(), true)
+				|| in_array(Stub::class, $type->getObjectClassNames(), true)
+			)
+			&& !$type->hasMethod($method)->yes()
+		) {
+			$mockClasses = array_filter($type->getObjectClassNames(), static fn (string $class): bool => $class !== MockObject::class && $class !== Stub::class);
+			if (count($mockClasses) === 0) {
+				return null;
+			}
+
+			return RuleErrorBuilder::message(sprintf(
 				'Trying to mock an undefined method %s() on class %s.',
 				$method,
-				implode('|', $classNames),
+				implode('&', $mockClasses),
 			))->identifier('phpunit.mockMethod')->build();
 		}
 
-		return $errors;
+		return null;
 	}
 
 }
diff --git a/src/Type/PHPUnit/InvocationMockerDynamicReturnTypeExtension.php b/src/Type/PHPUnit/InvocationMockerDynamicReturnTypeExtension.php
deleted file mode 100644
index 44764f6..0000000
--- a/src/Type/PHPUnit/InvocationMockerDynamicReturnTypeExtension.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php declare(strict_types = 1);
-
-namespace PHPStan\Type\PHPUnit;
-
-use PhpParser\Node\Expr\MethodCall;
-use PHPStan\Analyser\Scope;
-use PHPStan\Reflection\MethodReflection;
-use PHPStan\Type\DynamicMethodReturnTypeExtension;
-use PHPStan\Type\Type;
-use PHPUnit\Framework\MockObject\Builder\InvocationMocker;
-
-class InvocationMockerDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension
-{
-
-	public function getClass(): string
-	{
-		return InvocationMocker::class;
-	}
-
-	public function isMethodSupported(MethodReflection $methodReflection): bool
-	{
-		return $methodReflection->getName() !== 'getMatcher';
-	}
-
-	public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
-	{
-		return $scope->getType($methodCall->var);
-	}
-
-}
diff --git a/src/Type/PHPUnit/MockObjectDynamicReturnTypeExtension.php b/src/Type/PHPUnit/MockObjectDynamicReturnTypeExtension.php
deleted file mode 100644
index 626f168..0000000
--- a/src/Type/PHPUnit/MockObjectDynamicReturnTypeExtension.php
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php declare(strict_types = 1);
-
-namespace PHPStan\Type\PHPUnit;
-
-use PhpParser\Node\Expr\MethodCall;
-use PHPStan\Analyser\Scope;
-use PHPStan\Reflection\MethodReflection;
-use PHPStan\Type\DynamicMethodReturnTypeExtension;
-use PHPStan\Type\Generic\GenericObjectType;
-use PHPStan\Type\ObjectType;
-use PHPStan\Type\Type;
-use PHPUnit\Framework\MockObject\Builder\InvocationMocker;
-use PHPUnit\Framework\MockObject\MockObject;
-use function array_filter;
-use function array_values;
-use function count;
-
-class MockObjectDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension
-{
-
-	public function getClass(): string
-	{
-		return MockObject::class;
-	}
-
-	public function isMethodSupported(MethodReflection $methodReflection): bool
-	{
-		return $methodReflection->getName() === 'expects';
-	}
-
-	public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
-	{
-		$type = $scope->getType($methodCall->var);
-		$mockClasses = array_values(array_filter($type->getObjectClassNames(), static fn (string $class): bool => $class !== MockObject::class));
-
-		if (count($mockClasses) !== 1) {
-			return new ObjectType(InvocationMocker::class);
-		}
-
-		return new GenericObjectType(InvocationMocker::class, [new ObjectType($mockClasses[0])]);
-	}
-
-}
diff --git a/stubs/InvocationMocker.stub b/stubs/InvocationMocker.stub
deleted file mode 100644
index c58719f..0000000
--- a/stubs/InvocationMocker.stub
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php
-
-namespace PHPUnit\Framework\MockObject\Builder;
-
-use PHPUnit\Framework\MockObject\Stub;
-
-/**
- * @template TMockedClass
- */
-class InvocationMocker
-{
-
-}
diff --git a/tests/Rules/PHPUnit/MockMethodCallRuleTest.php b/tests/Rules/PHPUnit/MockMethodCallRuleTest.php
index c9c33e6..a7f7308 100644
--- a/tests/Rules/PHPUnit/MockMethodCallRuleTest.php
+++ b/tests/Rules/PHPUnit/MockMethodCallRuleTest.php
@@ -4,7 +4,6 @@
 
 use PHPStan\Rules\Rule;
 use PHPStan\Testing\RuleTestCase;
-use function interface_exists;
 
 /**
  * @extends RuleTestCase<MockMethodCallRule>
@@ -28,14 +27,11 @@ public function testRule(): void
 				'Trying to mock an undefined method doBadThing() on class MockMethodCall\Bar.',
 				20,
 			],
-		];
-
-		if (interface_exists('PHPUnit\Framework\MockObject\Builder\InvocationStubber')) {
-			$expectedErrors[] = [
+			[
 				'Trying to mock an undefined method doBadThing() on class MockMethodCall\Bar.',
 				36,
-			];
-		}
+			],
+		];
 
 		$this->analyse([__DIR__ . '/data/mock-method-call.php'], $expectedErrors);
 	}
diff --git a/tests/Type/PHPUnit/AssertFunctionTypeSpecifyingExtensionTest.php b/tests/Type/PHPUnit/AssertFunctionTypeSpecifyingExtensionTest.php
index 4405c4d..4014017 100644
--- a/tests/Type/PHPUnit/AssertFunctionTypeSpecifyingExtensionTest.php
+++ b/tests/Type/PHPUnit/AssertFunctionTypeSpecifyingExtensionTest.php
@@ -3,6 +3,7 @@
 namespace PHPStan\Type\PHPUnit;
 
 use PHPStan\Testing\TypeInferenceTestCase;
+use PHPUnit\Framework\Attributes\DataProvider;
 use function function_exists;
 
 class AssertFunctionTypeSpecifyingExtensionTest extends TypeInferenceTestCase
@@ -26,6 +27,7 @@ public static function dataFileAsserts(): iterable
 	 * @dataProvider dataFileAsserts
 	 * @param mixed ...$args
 	 */
+	#[DataProvider('dataFileAsserts')]
 	public function testFileAsserts(
 		string $assertType,
 		string $file,
diff --git a/tests/Type/PHPUnit/AssertMethodTypeSpecifyingExtensionTest.php b/tests/Type/PHPUnit/AssertMethodTypeSpecifyingExtensionTest.php
index 0b36c2b..8c6ebb8 100644
--- a/tests/Type/PHPUnit/AssertMethodTypeSpecifyingExtensionTest.php
+++ b/tests/Type/PHPUnit/AssertMethodTypeSpecifyingExtensionTest.php
@@ -3,6 +3,7 @@
 namespace PHPStan\Type\PHPUnit;
 
 use PHPStan\Testing\TypeInferenceTestCase;
+use PHPUnit\Framework\Attributes\DataProvider;
 
 class AssertMethodTypeSpecifyingExtensionTest extends TypeInferenceTestCase
 {
@@ -17,6 +18,7 @@ public static function dataFileAsserts(): iterable
 	 * @dataProvider dataFileAsserts
 	 * @param mixed ...$args
 	 */
+	#[DataProvider('dataFileAsserts')]
 	public function testFileAsserts(
 		string $assertType,
 		string $file,