2222use Symfony \Component \Validator \Context \ExecutionContextInterface ;
2323use Symfony \Component \Validator \Violation \ConstraintViolationBuilderInterface ;
2424
25+ /**
26+ * Concrete stub replacing getMockBuilder for ConstraintViolationBuilderInterface.
27+ * All fluent methods return `static` which PHPUnit <12.5 cannot mock.
28+ */
29+ class ConstraintViolationBuilderStub implements ConstraintViolationBuilderInterface
30+ {
31+ public bool $ violationAdded = false ;
32+ public array $ parameters = [];
33+
34+ public function atPath (string $ path ): static { return $ this ; }
35+ public function setParameter (string $ key , string $ value ): static { $ this ->parameters [$ key ] = $ value ; return $ this ; }
36+ public function setParameters (array $ parameters ): static { return $ this ; }
37+ public function disableTranslation (): static { return $ this ; }
38+ public function setTranslationDomain (string $ translationDomain ): static { return $ this ; }
39+ public function setInvalidValue (mixed $ invalidValue ): static { return $ this ; }
40+ public function setPlural (int $ number ): static { return $ this ; }
41+ public function setCode (?string $ code ): static { return $ this ; }
42+ public function setCause (mixed $ cause ): static { return $ this ; }
43+ public function addViolation (): void { $ this ->violationAdded = true ; }
44+ }
45+
2546#[AllowMockObjectsWithoutExpectations]
2647class FormTypeClassValidatorTest extends TestCase
2748{
@@ -31,10 +52,8 @@ class FormTypeClassValidatorTest extends TestCase
3152 * @var ExecutionContextInterface|MockObject
3253 */
3354 private MockObject $ executionContextMock ;
34- /**
35- * @var ConstraintViolationBuilderInterface|MockObject
36- */
37- private MockObject $ constraintViolationBuilderMock ;
55+
56+ private ConstraintViolationBuilderStub $ constraintViolationBuilderStub ;
3857
3958 protected function setUp (): void
4059 {
@@ -44,20 +63,14 @@ protected function setUp(): void
4463 ->disableOriginalConstructor ()
4564 ->getMock ();
4665
47- $ this ->constraintViolationBuilderMock = $ this ->getMockBuilder (ConstraintViolationBuilderInterface::class)
48- ->disableOriginalConstructor ()
49- ->getMock ();
66+ $ this ->constraintViolationBuilderStub = new ConstraintViolationBuilderStub ();
5067 }
5168
5269 private function initializeValidatorForNoErrors (): void
5370 {
5471 $ this ->executionContextMock
5572 ->expects ($ this ->never ())
5673 ->method ('buildViolation ' );
57-
58- $ this ->constraintViolationBuilderMock
59- ->expects ($ this ->never ())
60- ->method ('addViolation ' );
6174 $ this ->formTypeClassValidator ->initialize ($ this ->executionContextMock );
6275 }
6376
@@ -102,20 +115,13 @@ public function test_constraint_violation_for_invalid_class(): void
102115 ->expects (self ::once ())
103116 ->method ('buildViolation ' )
104117 ->with ($ constraint ->message )
105- ->willReturn ($ this ->constraintViolationBuilderMock );
118+ ->willReturn ($ this ->constraintViolationBuilderStub );
106119
107- $ this ->constraintViolationBuilderMock
108- ->expects (self ::once ())
109- ->method ('setParameter ' )
110- ->with ('{{ string }} ' , __CLASS__ )
111- ->willReturn ($ this ->constraintViolationBuilderMock );
112-
113- $ this ->constraintViolationBuilderMock
114- ->expects (self ::once ())
115- ->method ('addViolation ' );
116120 $ this ->formTypeClassValidator ->initialize ($ this ->executionContextMock );
117-
118121 $ this ->formTypeClassValidator ->validate (__CLASS__ , $ constraint );
122+
123+ $ this ->assertTrue ($ this ->constraintViolationBuilderStub ->violationAdded );
124+ $ this ->assertSame (__CLASS__ , $ this ->constraintViolationBuilderStub ->parameters ['{{ string }} ' ]);
119125 }
120126
121127 public function test_constraint_violation_for_string_that_is_not_a_class (): void
@@ -125,20 +131,13 @@ public function test_constraint_violation_for_string_that_is_not_a_class(): void
125131 $ this ->executionContextMock
126132 ->expects (self ::once ())
127133 ->method ('buildViolation ' )
128- ->willReturn ($ this ->constraintViolationBuilderMock );
134+ ->willReturn ($ this ->constraintViolationBuilderStub );
129135
130- $ this ->constraintViolationBuilderMock
131- ->expects (self ::once ())
132- ->method ('setParameter ' )
133- ->with ('{{ string }} ' , 'NotAClass ' )
134- ->willReturn ($ this ->constraintViolationBuilderMock );
135-
136- $ this ->constraintViolationBuilderMock
137- ->expects (self ::once ())
138- ->method ('addViolation ' );
139136 $ this ->formTypeClassValidator ->initialize ($ this ->executionContextMock );
140-
141137 $ this ->formTypeClassValidator ->validate ('NotAClass ' , $ constraint );
138+
139+ $ this ->assertTrue ($ this ->constraintViolationBuilderStub ->violationAdded );
140+ $ this ->assertSame ('NotAClass ' , $ this ->constraintViolationBuilderStub ->parameters ['{{ string }} ' ]);
142141 }
143142
144143 public function test_form_type_class_options_passed_to_parent (): void
0 commit comments