diff --git a/tests/api_controller_test.php b/tests/api_controller_test.php
index 1f8a28498ad4e24cfab3a17d19ac603a2348a42d..348d76d05977c55e0ca7972fe12a22eae7f508fd 100644
--- a/tests/api_controller_test.php
+++ b/tests/api_controller_test.php
@@ -40,25 +40,17 @@ use api\controller\TestController;
 use api\util\StackIframeHolder;
 use stack_api_test_data;
 use Psr\Http\Message\ResponseInterface as ResponseInt;
+use Psr\Http\Message\StreamInterface as StreamInt;
 use Psr\Http\Message\ServerRequestInterface as RequestInt;
 use qtype_stack_testcase;
 
-/**
- * Class to fake the response output object and store the actual JSON
- */
-class MockBody {
-    public object $output;
-    public function write() {
-        $this->output = json_decode(func_get_args()[0]);
-        return $this->output;
-    }
-}
-
 /**
  * @group qtype_stack
  * @covers \qtype_stack
  */
 class api_controller_test extends qtype_stack_testcase {
+    /** @var object used to store output */
+    public object $output;
     /** @var object used to store output */
     public object $result;
     /** @var array the api call data */
@@ -113,11 +105,27 @@ class api_controller_test extends qtype_stack_testcase {
             ->setMethods($methods)
             ->getMock();
 
-        $this->result = new MockBody();
+        $reflection = new \ReflectionClass(StreamInt::class);
+        $methods = [];
+        foreach ($reflection->getMethods() as $method) {
+            $methods[] = $method->name;
+        }
+
+        $this->result = $this->getMockBuilder(StreamInt::class)
+            ->setMockClassName('StreamInterface')
+            ->setMethods($methods)
+            ->getMock();
+
+        $this->result->expects($this->any())->method('write')->will($this->returnCallback(
+            function() {
+                $this->output = json_decode(func_get_args()[0]);
+                return 1;
+            })
+        );
 
-        // The controllers call getBody() on the response object but then call write() on the result.
-        // We return a MockBody object with a write method which updates the test's result property
-        // so we can actually perform some asserts.
+        // The controllers call getBody() on the response object but then call write() on the result
+        // so we have to mock both. We override the write method to write to a propery of the testsuite
+        // so we have something easily accessible to perform some asserts on.
         $this->response->expects($this->any())->method('getBody')->will($this->returnCallback(
             function() {
                 return $this->result;
@@ -140,18 +148,18 @@ class api_controller_test extends qtype_stack_testcase {
         $this->requestdata['questionDefinition'] = stack_api_test_data::get_question_string('matrices');
         $rc = new RenderController();
         $rc->__invoke($this->request, $this->response, []);
-        $this->assertMatchesRegularExpression('/^<p>Calculate/', $this->result->output->questionrender);
-        $this->assertEquals(86, $this->result->output->questionseed);
-        $this->assertEquals('matrix([35,30],[28,24])', $this->result->output->questioninputs->ans1->samplesolution->_val);
+        $this->assertMatchesRegularExpression('/^<p>Calculate/', $this->output->questionrender);
+        $this->assertEquals(86, $this->output->questionseed);
+        $this->assertEquals('matrix([35,30],[28,24])', $this->output->questioninputs->ans1->samplesolution->_val);
         $this->assertMatchesRegularExpression('/^<div class="matrixsquarebrackets"><table class="matrixtable"/',
-                $this->result->output->questioninputs->ans1->render);
-        $this->assertMatchesRegularExpression('/^<p>To multiply matrices/', $this->result->output->questionsamplesolutiontext);
-        $this->assertEquals(0, count((array)$this->result->output->questionassets));
-        $this->assertContains(86, $this->result->output->questionvariants);
-        $this->assertContains(219862533, $this->result->output->questionvariants);
-        $this->assertContains(1167893775, $this->result->output->questionvariants);
-        $this->assertEquals(3, count($this->result->output->questionvariants));
-        $this->assertEquals(0, count($this->result->output->iframes));
+                $this->output->questioninputs->ans1->render);
+        $this->assertMatchesRegularExpression('/^<p>To multiply matrices/', $this->output->questionsamplesolutiontext);
+        $this->assertEquals(0, count((array)$this->output->questionassets));
+        $this->assertContains(86, $this->output->questionvariants);
+        $this->assertContains(219862533, $this->output->questionvariants);
+        $this->assertContains(1167893775, $this->output->questionvariants);
+        $this->assertEquals(3, count($this->output->questionvariants));
+        $this->assertEquals(0, count($this->output->iframes));
     }
 
     public function test_render_specified_seed() {
@@ -159,33 +167,33 @@ class api_controller_test extends qtype_stack_testcase {
         $this->requestdata['questionDefinition'] = stack_api_test_data::get_question_string('matrices');
         $rc = new RenderController();
         $rc->__invoke($this->request, $this->response, []);
-        $this->assertMatchesRegularExpression('/^<p>Calculate/', $this->result->output->questionrender);
-        $this->assertEquals(219862533, $this->result->output->questionseed);
+        $this->assertMatchesRegularExpression('/^<p>Calculate/', $this->output->questionrender);
+        $this->assertEquals(219862533, $this->output->questionseed);
     }
 
     public function test_render_plots() {
         $this->requestdata['questionDefinition'] = stack_api_test_data::get_question_string('plots');
         $rc = new RenderController();
         $rc->__invoke($this->request, $this->response, []);
-        $this->assertEquals(4, count((array)$this->result->output->questionassets));
-        $this->assertEquals(true, isset($this->result->output->questionassets->{'input-ans1-1-0.svg'}));
-        $this->assertEquals(true, isset($this->result->output->questionassets->{'input-ans1-2-0.svg'}));
-        $this->assertEquals(true, isset($this->result->output->questionassets->{'input-ans1-3-0.svg'}));
-        $this->assertEquals(true, isset($this->result->output->questionassets->{'input-ans1-4-0.svg'}));
+        $this->assertEquals(4, count((array)$this->output->questionassets));
+        $this->assertEquals(true, isset($this->output->questionassets->{'input-ans1-1-0.svg'}));
+        $this->assertEquals(true, isset($this->output->questionassets->{'input-ans1-2-0.svg'}));
+        $this->assertEquals(true, isset($this->output->questionassets->{'input-ans1-3-0.svg'}));
+        $this->assertEquals(true, isset($this->output->questionassets->{'input-ans1-4-0.svg'}));
     }
 
     public function test_render_iframes() {
         $this->requestdata['questionDefinition'] = stack_api_test_data::get_question_string('iframes');
         $rc = new RenderController();
         $rc->__invoke($this->request, $this->response, []);
-        $this->assertEquals(1, count($this->result->output->iframes));
+        $this->assertEquals(1, count($this->output->iframes));
     }
 
     public function test_render_download() {
         $this->requestdata['questionDefinition'] = stack_api_test_data::get_question_string('download');
         $rc = new RenderController();
         $rc->__invoke($this->request, $this->response, []);
-        $this->assertMatchesRegularExpression('/javascript\:download\(\'data.csv\'\, 1\)/s', $this->result->output->questionrender);
+        $this->assertMatchesRegularExpression('/javascript\:download\(\'data.csv\'\, 1\)/s', $this->output->questionrender);
     }
 
     public function test_validation() {
@@ -195,8 +203,8 @@ class api_controller_test extends qtype_stack_testcase {
         $vc = new ValidationController();
         $vc->__invoke($this->request, $this->response, []);
         $this->assertMatchesRegularExpression('/\\\[ \\\left\[\\begin\{array\}\{cc\} 1 & 2 \\\\ 3 & 4 \\end{array}\\right\] \\\]/s',
-                $this->result->output->validation);
-        $this->assertEquals(0, count($this->result->output->iframes));
+                $this->output->validation);
+        $this->assertEquals(0, count($this->output->iframes));
     }
 
     public function test_grade() {
@@ -205,17 +213,17 @@ class api_controller_test extends qtype_stack_testcase {
         $this->requestdata['inputName'] = 'ans1';
         $gc = new GradingController();
         $gc->__invoke($this->request, $this->response, []);
-        $this->assertEquals(true, $this->result->output->isgradable);
-        $this->assertEquals(1, $this->result->output->score);
-        $this->assertEquals(1, $this->result->output->scores->prt1);
-        $this->assertEquals(1, $this->result->output->scores->total);
-        $this->assertEquals(1, $this->result->output->scoreweights->prt1);
-        $this->assertEquals(5, $this->result->output->scoreweights->total);
-        $this->assertEquals('<p>[[feedback:prt1]]</p>', $this->result->output->specificfeedback);
-        $this->assertStringContainsString('correct', $this->result->output->prts->prt1);
-        $this->assertEquals(0, count((array)$this->result->output->gradingassets));
-        $this->assertEquals('Seed: 86; ans1: matrix([35,30],[28,24]) [valid]; prt1: !', $this->result->output->responsesummary);
-        $this->assertEquals(0, count($this->result->output->iframes));
+        $this->assertEquals(true, $this->output->isgradable);
+        $this->assertEquals(1, $this->output->score);
+        $this->assertEquals(1, $this->output->scores->prt1);
+        $this->assertEquals(1, $this->output->scores->total);
+        $this->assertEquals(1, $this->output->scoreweights->prt1);
+        $this->assertEquals(5, $this->output->scoreweights->total);
+        $this->assertEquals('<p>[[feedback:prt1]]</p>', $this->output->specificfeedback);
+        $this->assertStringContainsString('correct', $this->output->prts->prt1);
+        $this->assertEquals(0, count((array)$this->output->gradingassets));
+        $this->assertEquals('Seed: 86; ans1: matrix([35,30],[28,24]) [valid]; prt1: !', $this->output->responsesummary);
+        $this->assertEquals(0, count($this->output->iframes));
     }
 
     public function test_grade_scores() {
@@ -224,18 +232,18 @@ class api_controller_test extends qtype_stack_testcase {
         $this->requestdata['inputName'] = 'ans1';
         $gc = new GradingController();
         $gc->__invoke($this->request, $this->response, []);
-        $this->assertEquals(true, $this->result->output->isgradable);
-        $this->assertEqualsWithDelta(0.9, $this->result->output->score, 0.0001);
-        $this->assertEquals(1, $this->result->output->scores->prt1);
-        $this->assertEquals(1, $this->result->output->scores->prt2);
-        $this->assertEquals(0, $this->result->output->scores->prt3);
-        $this->assertEquals(1, $this->result->output->scores->prt4);
-        $this->assertEqualsWithDelta(0.9, $this->result->output->scores->total, 0.0001);
-        $this->assertEqualsWithDelta(0.7, $this->result->output->scoreweights->prt1, 0.0001);
-        $this->assertEqualsWithDelta(0.1, $this->result->output->scoreweights->prt2, 0.0001);
-        $this->assertEqualsWithDelta(0.1, $this->result->output->scoreweights->prt3, 0.0001);
-        $this->assertEqualsWithDelta(0.1, $this->result->output->scoreweights->prt4, 0.0001);
-        $this->assertEquals(10, $this->result->output->scoreweights->total);
+        $this->assertEquals(true, $this->output->isgradable);
+        $this->assertEqualsWithDelta(0.9, $this->output->score, 0.0001);
+        $this->assertEquals(1, $this->output->scores->prt1);
+        $this->assertEquals(1, $this->output->scores->prt2);
+        $this->assertEquals(0, $this->output->scores->prt3);
+        $this->assertEquals(1, $this->output->scores->prt4);
+        $this->assertEqualsWithDelta(0.9, $this->output->scores->total, 0.0001);
+        $this->assertEqualsWithDelta(0.7, $this->output->scoreweights->prt1, 0.0001);
+        $this->assertEqualsWithDelta(0.1, $this->output->scoreweights->prt2, 0.0001);
+        $this->assertEqualsWithDelta(0.1, $this->output->scoreweights->prt3, 0.0001);
+        $this->assertEqualsWithDelta(0.1, $this->output->scoreweights->prt4, 0.0001);
+        $this->assertEquals(10, $this->output->scoreweights->total);
     }
 
     public function test_download() {
@@ -258,7 +266,7 @@ class api_controller_test extends qtype_stack_testcase {
         $this->requestdata['filepath'] = 'testpath/test.xml';
         $tc = new TestController();
         $tc->__invoke($this->request, $this->response, []);
-        $results = $this->result->output;
+        $results = $this->output;
         $this->assertEquals('test_3_matrix', $results->name);
         $this->assertEquals(false, $results->isupgradeerror);
         $this->assertEquals(true, $results->isgeneralfeedback );
@@ -278,7 +286,7 @@ class api_controller_test extends qtype_stack_testcase {
         $this->requestdata['filepath'] = 'testpath/test.xml';
         $tc = new TestController();
         $tc->__invoke($this->request, $this->response, []);
-        $results = $this->result->output;
+        $results = $this->output;
         $this->assertEquals('Algebraic input', $results->name);
         $this->assertEquals(false, $results->isupgradeerror);
         $this->assertEquals(false, $results->isgeneralfeedback );
@@ -299,7 +307,7 @@ class api_controller_test extends qtype_stack_testcase {
         $this->requestdata['filepath'] = 'testpath/test.xml';
         $tc = new TestController();
         $tc->__invoke($this->request, $this->response, []);
-        $results = $this->result->output;
+        $results = $this->output;
         $this->assertEquals('Algebraic input', $results->name);
         $this->assertEquals(true, $results->isupgradeerror);
         $this->assertEquals(false, $results->isgeneralfeedback );
@@ -315,7 +323,7 @@ class api_controller_test extends qtype_stack_testcase {
         $this->requestdata['filepath'] = 'testpath/test.xml';
         $tc = new TestController();
         $tc->__invoke($this->request, $this->response, []);
-        $results = $this->result->output;
+        $results = $this->output;
         $this->assertEquals('Algebraic input', $results->name);
         $this->assertEquals(false, $results->isupgradeerror);
         $this->assertEquals(false, $results->isgeneralfeedback );
@@ -333,7 +341,7 @@ class api_controller_test extends qtype_stack_testcase {
         $this->requestdata['filepath'] = 'testpath/test.xml';
         $tc = new TestController();
         $tc->__invoke($this->request, $this->response, []);
-        $results = $this->result->output;
+        $results = $this->output;
         $this->assertEquals('Algebraic input', $results->name);
         $this->assertEquals(false, $results->isupgradeerror);
         $this->assertEquals(false, $results->isgeneralfeedback );