@@ -56,7 +56,7 @@ final public function runAsyncTest(...$args)
56
56
$ start = \microtime (true );
57
57
58
58
Loop::run (function () use (&$ returnValue , &$ exception , &$ invoked , $ args ) {
59
- $ promise = $ this ->call ([ $ this , $ this -> realTestName ], ... $ args );
59
+ $ promise = new Coroutine ( $ this ->runAsyncTestCycle ( $ args) );
60
60
$ promise ->onResolve (function ($ error , $ value ) use (&$ invoked , &$ exception , &$ returnValue ) {
61
61
$ invoked = true ;
62
62
$ exception = $ error ;
@@ -91,12 +91,63 @@ final public function runAsyncTest(...$args)
91
91
return $ returnValue ;
92
92
}
93
93
94
+ private function runAsyncTestCycle (array $ args ): \Generator
95
+ {
96
+ try {
97
+ yield $ this ->call (\Closure::fromCallable ([$ this , 'setUpAsync ' ]));
98
+ } catch (\Throwable $ exception ) {
99
+ throw new \Error (\sprintf (
100
+ '%s::setUpAsync() failed ' ,
101
+ \str_replace ("\0" , '@ ' , \get_class ($ this )) // replace NUL-byte in anonymous class name
102
+ ), 0 , $ exception );
103
+ }
104
+
105
+ try {
106
+ $ returnValue = yield $ this ->call ([$ this , $ this ->realTestName ], ...$ args );
107
+ } catch (\Throwable $ testException ) {
108
+ // Exception rethrown in finally block below
109
+ }
110
+
111
+ try {
112
+ yield $ this ->call (\Closure::fromCallable ([$ this , 'tearDownAsync ' ]));
113
+ } catch (\Throwable $ exception ) {
114
+ throw new \Error (\sprintf (
115
+ '%s::tearDownAsync() failed ' ,
116
+ \str_replace ("\0" , '@ ' , \get_class ($ this )) // replace NUL-byte in anonymous class name
117
+ ), 0 , $ exception );
118
+ } finally {
119
+ if (isset ($ testException )) {
120
+ throw $ testException ;
121
+ }
122
+ }
123
+
124
+ return $ returnValue ;
125
+ }
126
+
94
127
final protected function runTest ()
95
128
{
96
129
parent ::setName ('runAsyncTest ' );
97
130
return parent ::runTest ();
98
131
}
99
132
133
+ /**
134
+ * Called before each test. Similar to {@see TestCase::setUp()}, except the method may return a promise or
135
+ * coroutine (@see \Amp\call()} that will be awaited before executing the test.
136
+ */
137
+ protected function setUpAsync ()
138
+ {
139
+ // Empty method to be overloaded by inheriting class if desired.
140
+ }
141
+
142
+ /**
143
+ * Called after each test. Similar to {@see TestCase::tearDown()}, except the method may return a promise or
144
+ * coroutine (@see \Amp\call()} that will be awaited before executing the next test.
145
+ */
146
+ protected function tearDownAsync ()
147
+ {
148
+ // Empty method to be overloaded by inheriting class if desired.
149
+ }
150
+
100
151
/**
101
152
* Fails the test if the loop does not run for at least the given amount of time.
102
153
*
0 commit comments