diff --git a/module/VuFind/src/VuFindTest/Unit/FixtureTrait.php b/module/VuFind/src/VuFindTest/Unit/FixtureTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..1aac9193de643e65257dfb0bf6ae7e823666a6e8
--- /dev/null
+++ b/module/VuFind/src/VuFindTest/Unit/FixtureTrait.php
@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * Trait adding functionality for loading fixtures.
+ *
+ * PHP version 7
+ *
+ * Copyright (C) Villanova University 2020.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ */
+namespace VuFindTest\Unit;
+
+use RuntimeException;
+
+/**
+ * Trait adding functionality for loading fixtures.
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ */
+trait FixtureTrait
+{
+    /**
+     * Get the base directory containing fixtures.
+     *
+     * @param string $module Module containing fixture.
+     *
+     * @return string
+     */
+    protected function getFixtureDir($module = 'VuFind')
+    {
+        return __DIR__ . '/../../../../' . $module . '/tests/fixtures/';
+    }
+
+    /**
+     * Load a fixture file.
+     *
+     * @param string $filename Filename relative to fixture directory.
+     * @param string $module   Module containing fixture.
+     *
+     * @return string
+     * @throws RuntimeException
+     */
+    protected function getFixture($filename, $module = 'VuFind')
+    {
+        $realFilename = realpath($this->getFixtureDir($module) . $filename);
+        if (!$realFilename || !file_exists($realFilename)
+            || !is_readable($realFilename)
+        ) {
+            throw new RuntimeException(
+                sprintf('Unable to resolve fixture to fixture file: %s', $filename)
+            );
+        }
+        return file_get_contents($realFilename);
+    }
+
+    /**
+     * Load a JSON fixture from file (using associative array return type).
+     *
+     * @param string $filename Filename relative to fixture directory.
+     * @param string $module   Module containing fixture.
+     *
+     * @return array
+     */
+    protected function getJsonFixture($filename, $module = 'VuFind')
+    {
+        return json_decode($this->getFixture($filename, $module), true);
+    }
+}
diff --git a/module/VuFind/tests/bootstrap.php b/module/VuFind/tests/bootstrap.php
index 05bef2d6ab8e1119670aaa94d2bdd412d51094fc..571aecd166685d4add1a78e6547a8f1131d6576f 100644
--- a/module/VuFind/tests/bootstrap.php
+++ b/module/VuFind/tests/bootstrap.php
@@ -1,8 +1,5 @@
 <?php
 
-// Set path to this module
-define('VUFIND_PHPUNIT_MODULE_PATH', __DIR__);
-
 // Define path to application directory
 defined('APPLICATION_PATH')
     || define(
@@ -64,5 +61,3 @@ if (file_exists('vendor/autoload.php')) {
     }
     $loader->register();
 }
-
-define('PHPUNIT_SEARCH_FIXTURES', realpath(__DIR__ . '/../../VuFindSearch/tests/unit-tests/fixtures'));
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/SearchSpecsReaderTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/SearchSpecsReaderTest.php
index ca4ebc4821012c75e5094961e88ce7b932018ce6..60c129938709538f8b7306bb53e69b46e85c627e 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/SearchSpecsReaderTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/SearchSpecsReaderTest.php
@@ -42,6 +42,8 @@ use VuFind\Config\SearchSpecsReader;
  */
 class SearchSpecsReaderTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Flag -- did writing config files fail?
      *
@@ -122,8 +124,8 @@ class SearchSpecsReaderTest extends \VuFindTest\Unit\TestCase
     public function testYamlLoad()
     {
         $reader = new SearchSpecsReader();
-        $core = __DIR__ . '/../../../../fixtures/configs/yaml/core.yaml';
-        $local = __DIR__ . '/../../../../fixtures/configs/yaml/local.yaml';
+        $core = $this->getFixtureDir() . 'configs/yaml/core.yaml';
+        $local = $this->getFixtureDir() . 'configs/yaml/local.yaml';
         $this->assertEquals(
             [
                 'top' => ['foo' => 'bar'],
@@ -148,8 +150,8 @@ class SearchSpecsReaderTest extends \VuFindTest\Unit\TestCase
     public function testYamlMerge()
     {
         $reader = new SearchSpecsReader();
-        $core = __DIR__ . '/../../../../fixtures/configs/yaml/core.yaml';
-        $local = __DIR__ . '/../../../../fixtures/configs/yaml/local.yaml';
+        $core = $this->getFixtureDir() . 'configs/yaml/core.yaml';
+        $local = $this->getFixtureDir() . 'configs/yaml/local.yaml';
         $this->assertEquals(
             [
                 'top' => ['foo' => 'xyzzy'],
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php
index 4914e862e98d8cc55eff1034a7fa28c3b08f34e7..c95afffbafc87683ed8ad4ef80628b0e22e5b80c 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php
@@ -41,6 +41,8 @@ use VuFind\Config\Upgrade;
  */
 class UpgradeTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Target upgrade version
      *
@@ -57,7 +59,7 @@ class UpgradeTest extends \VuFindTest\Unit\TestCase
      */
     protected function getUpgrader($version)
     {
-        $oldDir = realpath(__DIR__ . '/../../../../fixtures/configs/' . $version);
+        $oldDir = realpath($this->getFixtureDir() . 'configs/' . $version);
         $rawDir = realpath(__DIR__ . '/../../../../../../../config/vufind');
         return new Upgrade($version, $this->targetVersion, $oldDir, $rawDir);
     }
@@ -469,7 +471,7 @@ class UpgradeTest extends \VuFindTest\Unit\TestCase
     {
         $upgrader = $this->getUpgrader('1.4');
         $meaningless = realpath(
-            __DIR__ . '/../../../../fixtures/configs/solrmarc/empty.properties'
+            $this->getFixtureDir() . 'configs/solrmarc/empty.properties'
         );
         $this->assertFalse(
             $this->callMethod(
@@ -477,7 +479,7 @@ class UpgradeTest extends \VuFindTest\Unit\TestCase
             )
         );
         $meaningful = realpath(
-            __DIR__ . '/../../../../fixtures/configs/solrmarc/meaningful.properties'
+            $this->getFixtureDir() . 'configs/solrmarc/meaningful.properties'
         );
         $this->assertTrue(
             $this->callMethod(
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/VersionTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/VersionTest.php
index a4d73ad9265e7fd286de426c378ff2901689c309..1c72d62afeac32d411fac0101094ccc18519fd03 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/VersionTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/VersionTest.php
@@ -41,6 +41,8 @@ use VuFind\Config\Version;
  */
 class VersionTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test the default directory parameter.
      *
@@ -75,7 +77,7 @@ class VersionTest extends \VuFindTest\Unit\TestCase
      */
     public function testKnownVersion()
     {
-        $fixture = __DIR__ . '/../../../../fixtures/configs/buildxml-2.5';
+        $fixture = $this->getFixtureDir() . 'configs/buildxml-2.5';
         $this->assertEquals('2.5', Version::getBuildVersion($fixture));
     }
 }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/WriterTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/WriterTest.php
index 698bcbb26e47edb5ba469000ba2b8000ffc3d129..05b94d6fddacb6ff061b6eac0fbcf55d52355ef5 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/WriterTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/WriterTest.php
@@ -41,6 +41,8 @@ use VuFind\Config\Writer;
  */
 class WriterTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test reading from a file.
      *
@@ -48,9 +50,10 @@ class WriterTest extends \VuFindTest\Unit\TestCase
      */
     public function testReadFile()
     {
-        $file = realpath(__DIR__ . '/../../../../fixtures/configs/1.1/sms.ini');
-        $test = new Writer($file);
-        $this->assertEquals(file_get_contents($file), $test->getContent());
+        $test = new Writer($this->getFixtureDir() . 'configs/1.1/sms.ini');
+        $this->assertEquals(
+            $this->getFixture('configs/1.1/sms.ini'), $test->getContent()
+        );
     }
 
     /**
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Connection/WikipediaTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Connection/WikipediaTest.php
index 28048abe0e6cb9d97478089dce1e4a011bb6c94d..08c61c7e0f33e402049d6f5b88fb83bd04853b6a 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Connection/WikipediaTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Connection/WikipediaTest.php
@@ -44,6 +44,8 @@ use VuFind\Connection\Wikipedia;
  */
 class WikipediaTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test processing of English-language Jane Austen entry.
      *
@@ -68,9 +70,8 @@ class WikipediaTest extends \PHPUnit\Framework\TestCase
      */
     protected function getClient($fixture)
     {
-        $file = realpath(__DIR__ . '/../../../../fixtures/wikipedia/' . $fixture);
         $adapter = new TestAdapter();
-        $adapter->setResponse(file_get_contents($file));
+        $adapter->setResponse($this->getFixture("wikipedia/$fixture"));
         $client = new HttpClient();
         $client->setAdapter($adapter);
         return $client;
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Connection/WorldCatUtilsTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Connection/WorldCatUtilsTest.php
index 23d3915fe526d8435881dd1ed66902180f1ace51..245f032fec6afae725c1d3ea7298a42e976572e3 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Connection/WorldCatUtilsTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Connection/WorldCatUtilsTest.php
@@ -44,6 +44,8 @@ use VuFind\Connection\WorldCatUtils;
  */
 class WorldCatUtilsTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test related identities
      *
@@ -82,8 +84,7 @@ class WorldCatUtilsTest extends \PHPUnit\Framework\TestCase
         $client = new HttpClient();
         if (null !== $fixture) {
             $adapter = new TestAdapter();
-            $file = realpath(__DIR__ . '/../../../../fixtures/worldcat/' . $fixture);
-            $adapter->setResponse(file_get_contents($file));
+            $adapter->setResponse($this->getFixture("worldcat/$fixture"));
             $client->setAdapter($adapter);
         }
         return new WorldCatUtils('dummy', $client, $silent);
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Content/PageLocatorTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Content/PageLocatorTest.php
index 578830b1282389ff8563e2e28b7b36867a978f5a..9e2592aca204771951eb9f1ff87da566703f99f0 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Content/PageLocatorTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Content/PageLocatorTest.php
@@ -42,32 +42,25 @@ use VuFindTheme\ThemeInfo;
  */
 class PageLocatorTest extends \VuFindTest\Unit\TestCase
 {
-    /**
-     * Path to theme fixtures
-     *
-     * @var string
-     */
-    protected $fixturePath;
+    use \VuFindTest\Unit\FixtureTrait;
 
     /**
-     * Constructor
+     * Test determining a template and renderer.
+     *
+     * @return void
      */
-    public function setUp(): void
-    {
-        $this->fixturePath = realpath(__DIR__ . '/../../../../../../VuFindTheme/tests/unit-tests/fixtures/themes');
-    }
-
     public function testDetermineTemplateAndRenderer()
     {
         $language  = 'aa';
         $defaultLanguage = 'bb';
         $pathPrefix = 'templates/page-locator-test/';
+        $fixturePath = $this->getFixtureDir('VuFindTheme') . 'themes/';
         $testCases = [
             [
                 'pageName' => 'page1',
                 'result' => [
                     'renderer' => 'phtml',
-                    'path' => $this->fixturePath . '/parent/templates/page-locator-test/page1.phtml',
+                    'path' => $fixturePath . 'parent/templates/page-locator-test/page1.phtml',
                     'page' => 'page1',
                 ],
             ],
@@ -75,7 +68,7 @@ class PageLocatorTest extends \VuFindTest\Unit\TestCase
                 'pageName' => 'page2',
                 'result' => [
                     'renderer' => 'phtml',
-                    'path' => $this->fixturePath . '/parent/templates/page-locator-test/page2_aa.phtml',
+                    'path' => $fixturePath . 'parent/templates/page-locator-test/page2_aa.phtml',
                     'page' => 'page2_aa',
                 ],
             ],
@@ -83,7 +76,7 @@ class PageLocatorTest extends \VuFindTest\Unit\TestCase
                 'pageName' => 'page3',
                 'result' => [
                     'renderer' => 'phtml',
-                    'path' => $this->fixturePath . '/parent/templates/page-locator-test/page3_bb.phtml',
+                    'path' => $fixturePath . 'parent/templates/page-locator-test/page3_bb.phtml',
                     'page' => 'page3_bb',
                 ],
             ],
@@ -91,7 +84,7 @@ class PageLocatorTest extends \VuFindTest\Unit\TestCase
                 'pageName' => 'page4',
                 'result' => [
                     'renderer' => 'md',
-                    'path' => $this->fixturePath . '/parent/templates/page-locator-test/page4.md',
+                    'path' => $fixturePath . 'parent/templates/page-locator-test/page4.md',
                     'page' => 'page4',
                 ],
             ],
@@ -99,7 +92,7 @@ class PageLocatorTest extends \VuFindTest\Unit\TestCase
                 'pageName' => 'page5',
                 'result' => [
                     'renderer' => 'md',
-                    'path' => $this->fixturePath . '/parent/templates/page-locator-test/page5_aa.md',
+                    'path' => $fixturePath . 'parent/templates/page-locator-test/page5_aa.md',
                     'page' => 'page5_aa',
                 ],
             ],
@@ -107,7 +100,7 @@ class PageLocatorTest extends \VuFindTest\Unit\TestCase
                 'pageName' => 'page6',
                 'result' => [
                     'renderer' => 'md',
-                    'path' => $this->fixturePath . '/parent/templates/page-locator-test/page6_bb.md',
+                    'path' => $fixturePath . 'parent/templates/page-locator-test/page6_bb.md',
                     'page' => 'page6_bb',
                 ],
             ],
@@ -116,20 +109,10 @@ class PageLocatorTest extends \VuFindTest\Unit\TestCase
                 'result' => null,
             ],
         ];
-        $themeInfo = $this->getThemeInfo();
+        $themeInfo = new ThemeInfo(rtrim($fixturePath, '/'), 'parent');
         $pageLocator = new PageLocator($themeInfo, $language, $defaultLanguage);
         foreach ($testCases as $case) {
             $this->assertEquals($case['result'], $pageLocator->determineTemplateAndRenderer($pathPrefix, $case['pageName']));
         }
     }
-
-    /**
-     * Get a test object
-     *
-     * @return ThemeInfo
-     */
-    protected function getThemeInfo()
-    {
-        return new ThemeInfo($this->fixturePath, 'parent');
-    }
 }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/ContentBlock/TemplateBasedTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/ContentBlock/TemplateBasedTest.php
index b9f1b10db812f9605b38de5e940481c9a45f3fb3..6fde869b38f3757d8ff6c29328eaa1c584b90310 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/ContentBlock/TemplateBasedTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/ContentBlock/TemplateBasedTest.php
@@ -38,6 +38,8 @@ namespace VuFindTest\ContentBlock;
  */
 class TemplateBasedTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test basic functionality of .phtml content block.
      *
@@ -63,7 +65,7 @@ class TemplateBasedTest extends \PHPUnit\Framework\TestCase
      */
     public function testBasicMarkdownFunctionality()
     {
-        $fixturePath = realpath(__DIR__ . '/../../../../../../VuFindTheme/tests/unit-tests/fixtures/themes');
+        $fixturePath = realpath($this->getFixtureDir('VuFindTheme') . 'themes');
         $file = $fixturePath . '/parent/templates/page-locator-test/page4.md';
         $locator = $this->getMockBuilder(\VuFind\Content\PageLocator::class)
             ->disableOriginalConstructor()
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/DoiLinker/BrowZineTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/DoiLinker/BrowZineTest.php
index acdee46d1f0573d608414c6009700cbdf1653715..aeeb98b282b2f2ca060e27170addc464d06ac18e 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/DoiLinker/BrowZineTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/DoiLinker/BrowZineTest.php
@@ -41,6 +41,8 @@ use VuFindSearch\Backend\BrowZine\Connector;
  */
 class BrowZineTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Get a mock connector
      *
@@ -68,11 +70,7 @@ class BrowZineTest extends \VuFindTest\Unit\TestCase
      */
     public function testApiSuccess()
     {
-        $fixture = realpath(
-            __DIR__
-            . '/../../../../../tests/fixtures/browzine/doi.json'
-        );
-        $rawData = json_decode(file_get_contents($fixture), true);
+        $rawData = $this->getJsonFixture('browzine/doi.json');
         $testData = [
             [
                 'config' => [],
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/DoiLinker/UnpaywallTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/DoiLinker/UnpaywallTest.php
index faf7deef3b7bcca15b4131e40333783bb9321ba1..54a1251e03308b9696b9998578023a9fdab1b4c1 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/DoiLinker/UnpaywallTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/DoiLinker/UnpaywallTest.php
@@ -42,6 +42,8 @@ use VuFind\DoiLinker\Unpaywall;
  */
 class UnpaywallTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test configuration validation.
      *
@@ -65,10 +67,7 @@ class UnpaywallTest extends \VuFindTest\Unit\TestCase
         $adapter = new TestAdapter();
         $testData = [
             [
-                'filename' => realpath(
-                    __DIR__
-                    . '/../../../../../tests/fixtures/unpaywall/goodresponsepdf'
-                ),
+                'fixture' => $this->getFixture('unpaywall/goodresponsepdf'),
                 'response' => [
                     '10.7553/66-4-1434' => [
                         [
@@ -79,10 +78,7 @@ class UnpaywallTest extends \VuFindTest\Unit\TestCase
                 ]
             ],
             [
-                'filename' => realpath(
-                    __DIR__
-                    . '/../../../../../tests/fixtures/unpaywall/goodresponseonline'
-                ),
+                'fixture' => $this->getFixture('unpaywall/goodresponseonline'),
                 'response' => [
                     '10.7553/66-4-1434' => [
                         [
@@ -93,10 +89,7 @@ class UnpaywallTest extends \VuFindTest\Unit\TestCase
                 ]
             ],
             [
-                'filename' => realpath(
-                    __DIR__
-                    . '/../../../../../tests/fixtures/unpaywall/badresponse'
-                ),
+                'fixture' => $this->getFixture('unpaywall/badresponse'),
                 'response' => []
             ],
         ];
@@ -107,8 +100,7 @@ class UnpaywallTest extends \VuFindTest\Unit\TestCase
         $unpaywall = new Unpaywall(new \Laminas\Config\Config($config));
 
         foreach ($testData as $data) {
-            $response = file_get_contents($data['filename']);
-            $responseObj = HttpResponse::fromString($response);
+            $responseObj = HttpResponse::fromString($data['fixture']);
             $adapter->setResponse($responseObj);
             $service = new \VuFindHttp\HttpService();
             $service->setDefaultAdapter($adapter);
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Form/FormTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Form/FormTest.php
index 492317d2980ec914dee1bd349d88673222887b28..933b378e6a619ec3ea303c11f261387c58b0d051 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Form/FormTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Form/FormTest.php
@@ -42,6 +42,8 @@ use VuFind\Form\Form;
  */
 class FormTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test defaults with no configuration.
      *
@@ -219,11 +221,7 @@ class FormTest extends \VuFindTest\Unit\TestCase
      */
     public function testElementOptions()
     {
-        $config = Yaml::parse(
-            file_get_contents(
-                __DIR__ . '/../../../../fixtures/configs/feedbackforms/test.yaml'
-            )
-        );
+        $config = Yaml::parse($this->getFixture('configs/feedbackforms/test.yaml'));
         $mock = $this->getMockBuilder(\VuFind\Config\YamlReader::class)
             ->disableOriginalConstructor()
             ->setMethods(['get'])
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/I18n/Translator/Loader/ExtendedIniTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/I18n/Translator/Loader/ExtendedIniTest.php
index af66f5fccc78a1d20b64dd2e6ecaf65a1cbade6f..ee730bba71b2911cd84017472f94ab1faa9fc1f8 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/I18n/Translator/Loader/ExtendedIniTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/I18n/Translator/Loader/ExtendedIniTest.php
@@ -41,6 +41,8 @@ use VuFind\I18n\Translator\Loader\ExtendedIni;
  */
 class ExtendedIniTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test translations.
      *
@@ -49,8 +51,8 @@ class ExtendedIniTest extends \VuFindTest\Unit\TestCase
     public function testTranslations()
     {
         $pathStack = [
-            realpath(__DIR__ . '/../../../../../../fixtures/language/base'),
-            realpath(__DIR__ . '/../../../../../../fixtures/language/overrides')
+            realpath($this->getFixtureDir() . 'language/base'),
+            realpath($this->getFixtureDir() . 'language/overrides')
         ];
         $loader = new ExtendedIni($pathStack);
         $result = $loader->load('en', null);
@@ -73,7 +75,7 @@ class ExtendedIniTest extends \VuFindTest\Unit\TestCase
     public function testFallback()
     {
         $pathStack = [
-            realpath(__DIR__ . '/../../../../../../fixtures/language/base'),
+            realpath($this->getFixtureDir() . 'language/base'),
         ];
         $loader = new ExtendedIni($pathStack, 'en');
         $result = $loader->load('fake', null);
@@ -97,7 +99,7 @@ class ExtendedIniTest extends \VuFindTest\Unit\TestCase
     public function testFallbackToSelf()
     {
         $pathStack = [
-            realpath(__DIR__ . '/../../../../../../fixtures/language/base'),
+            realpath($this->getFixtureDir() . 'language/base'),
         ];
         $loader = new ExtendedIni($pathStack, 'fake');
         $result = $loader->load('fake', null);
@@ -117,7 +119,7 @@ class ExtendedIniTest extends \VuFindTest\Unit\TestCase
     public function testSelfAsParent()
     {
         $pathStack = [
-            realpath(__DIR__ . '/../../../../../../fixtures/language/base'),
+            realpath($this->getFixtureDir() . 'language/base'),
         ];
         $loader = new ExtendedIni($pathStack);
         $result = $loader->load('self-parent', null);
@@ -138,7 +140,7 @@ class ExtendedIniTest extends \VuFindTest\Unit\TestCase
     public function testParentChain()
     {
         $pathStack = [
-            realpath(__DIR__ . '/../../../../../../fixtures/language/base'),
+            realpath($this->getFixtureDir() . 'language/base'),
         ];
         $loader = new ExtendedIni($pathStack);
         $result = $loader->load('child2', null);
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/DAIATest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/DAIATest.php
index 78398a70bbc500b038b9b618f95a94746ac7171b..f857c283744bfd4cbd22146184f2912999bbd282 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/DAIATest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/DAIATest.php
@@ -46,6 +46,8 @@ use VuFind\ILS\Driver\DAIA;
  */
 class DAIATest extends \VuFindTest\Unit\ILSDriverTestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     protected $testResult = [
         0 =>
             [
@@ -209,17 +211,9 @@ class DAIATest extends \VuFindTest\Unit\ILSDriverTestCase
     {
         $adapter = new TestAdapter();
         if ($fixture) {
-            $file = realpath(
-                __DIR__ .
-                '/../../../../../../tests/fixtures/daia/response/' . $fixture
+            $responseObj = HttpResponse::fromString(
+                $this->getFixture("daia/response/$fixture")
             );
-            if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-                throw new InvalidArgumentException(
-                    sprintf('Unable to load fixture file: %s ', $file)
-                );
-            }
-            $response = file_get_contents($file);
-            $responseObj = HttpResponse::fromString($response);
             $adapter->setResponse($responseObj);
         }
         $service = new \VuFindHttp\HttpService();
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/FolioTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/FolioTest.php
index bb911a5283af868f96bfa38ba0bee25bad7aefc6..d7c44abab7af616a0d9492144282d9af765a7b6a 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/FolioTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/FolioTest.php
@@ -28,8 +28,6 @@
  */
 namespace VuFindTest\ILS\Driver;
 
-use InvalidArgumentException;
-
 use VuFind\ILS\Driver\Folio;
 
 /**
@@ -43,6 +41,8 @@ use VuFind\ILS\Driver\Folio;
  */
 class FolioTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     protected $testConfig = [
         'API' => [
             'base_url' => 'localhost',
@@ -99,16 +99,7 @@ class FolioTest extends \VuFindTest\Unit\TestCase
     protected function createConnector($test)
     {
         // Setup test responses
-        $file = realpath(
-            __DIR__ .
-            '/../../../../../../tests/fixtures/folio/responses/' . $test . '.json'
-        );
-        if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-            throw new InvalidArgumentException(
-                sprintf('Unable to load fixture file: %s ', $file)
-            );
-        }
-        $this->testResponses = json_decode(file_get_contents($file), true);
+        $this->testResponses = $this->getJsonFixture("folio/responses/$test.json");
         // Reset log
         $this->testRequestLog = [];
         // Session factory
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/PAIATest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/PAIATest.php
index 486db2cbf06cca580667217d9ea3edf8c16c72cf..5049b13505f28b6d673a4a87162ca229f82464cc 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/PAIATest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/PAIATest.php
@@ -46,6 +46,8 @@ use VuFind\ILS\Driver\PAIA;
  */
 class PAIATest extends \VuFindTest\Unit\ILSDriverTestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     protected $validConfig = [
         'DAIA' =>
             [
@@ -562,17 +564,9 @@ class PAIATest extends \VuFindTest\Unit\ILSDriverTestCase
     {
         $adapter = new TestAdapter();
         if ($fixture) {
-            $file = realpath(
-                __DIR__ .
-                '/../../../../../../tests/fixtures/paia/response/' . $fixture
+            $responseObj = HttpResponse::fromString(
+                $this->getFixture("paia/response/$fixture")
             );
-            if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-                throw new InvalidArgumentException(
-                    sprintf('Unable to load fixture file: %s ', $file)
-                );
-            }
-            $response = file_get_contents($file);
-            $responseObj = HttpResponse::fromString($response);
             $adapter->setResponse($responseObj);
         }
         $service = new \VuFindHttp\HttpService();
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/XCNCIP2Test.php b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/XCNCIP2Test.php
index 0e74dd84771a4def32d31e92ae15f67cee532750..21645831fd94fed1a3da18091c7622facf56b52e 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/XCNCIP2Test.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/XCNCIP2Test.php
@@ -43,6 +43,8 @@ use VuFind\ILS\Driver\XCNCIP2;
  */
 class XCNCIP2Test extends \VuFindTest\Unit\ILSDriverTestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Standard setup method.
      *
@@ -1278,17 +1280,9 @@ class XCNCIP2Test extends \VuFindTest\Unit\ILSDriverTestCase
      */
     protected function loadResponse($filename)
     {
-        $file = realpath(
-            __DIR__ .
-            '/../../../../../../tests/fixtures/xcncip2/response/' . $filename
+        return HttpResponse::fromString(
+            $this->getFixture("xcncip2/response/$filename")
         );
-        if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-            throw new InvalidArgumentException(
-                sprintf('Unable to load fixture file: %s ', $file)
-            );
-        }
-        $response = file_get_contents($file);
-        return HttpResponse::fromString($response);
     }
 
     /**
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Recommend/EuropeanaResultsTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Recommend/EuropeanaResultsTest.php
index ec925a6867b533c5536a7675ca0b47478c1a28c7..2776814e3a0895620483878af2d9914c78541ac6 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Recommend/EuropeanaResultsTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Recommend/EuropeanaResultsTest.php
@@ -44,6 +44,8 @@ use VuFindTest\Unit\TestCase as TestCase;
  */
 class EuropeanaResultsTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test that the module properly parses a sample response.
      *
@@ -110,24 +112,13 @@ class EuropeanaResultsTest extends TestCase
     {
         $adapter = new TestAdapter();
         if ($fixture) {
-            $adapter->setResponse($this->loadResponse($fixture));
+            $adapter->setResponse($this->getFixture("recommend/$fixture"));
         }
         $service = new HttpService();
         $service->setDefaultAdapter($adapter);
         return $service;
     }
 
-    /**
-     * Get a fixture response
-     *
-     * @return string
-     */
-    protected function loadResponse($file)
-    {
-        $fixturePath = realpath(__DIR__ . '/../../../../fixtures/recommend') . '/';
-        return file_get_contents($fixturePath . $file);
-    }
-
     /**
      * Get a mock results object.
      *
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Recommend/RandomRecommendTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Recommend/RandomRecommendTest.php
index 42a41ebd5b823a88e67e5d0a2be5e47fdc6ae41f..c08abbd281520848c9fec8914d7cdfd0102de87f 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Recommend/RandomRecommendTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Recommend/RandomRecommendTest.php
@@ -42,6 +42,8 @@ use VuFindTest\Unit\TestCase as TestCase;
  */
 class RandomRecommendTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Standard setup method.
      *
@@ -129,7 +131,7 @@ class RandomRecommendTest extends TestCase
         // Use Solr since some Base components are abstract:
         $params = $this->getServiceManager()
             ->get(\VuFind\Search\Params\PluginManager::class)->get('Solr');
-        $query = $this->getFixture('query');
+        $query = $this->unserializeFixture('query');
         $params->setBasicSearch($query->getString(), $query->getHandler());
         $request = $this->createMock(\Laminas\Stdlib\Parameters::class);
 
@@ -167,7 +169,7 @@ class RandomRecommendTest extends TestCase
         // Use Solr since some Base components are abstract:
         $params = $this->getServiceManager()
             ->get(\VuFind\Search\Params\PluginManager::class)->get('Solr');
-        $query = $this->getFixture('query');
+        $query = $this->unserializeFixture('query');
         $params->setBasicSearch($query->getString(), $query->getHandler());
         $request = $this->createMock(\Laminas\Stdlib\Parameters::class);
 
@@ -195,7 +197,7 @@ class RandomRecommendTest extends TestCase
         $results = $this->getServiceManager()
             ->get(\VuFind\Search\Results\PluginManager::class)->get('Solr');
         $params = $results->getParams();
-        $query = $this->getFixture('query');
+        $query = $this->unserializeFixture('query');
         $params->setBasicSearch($query->getString(), $query->getHandler());
         $request = $this->createMock(\Laminas\Stdlib\Parameters::class);
 
@@ -233,7 +235,7 @@ class RandomRecommendTest extends TestCase
         $results = $this->getServiceManager()
             ->get(\VuFind\Search\Results\PluginManager::class)->get('Solr');
         $params = $results->getParams();
-        $query = $this->getFixture('query');
+        $query = $this->unserializeFixture('query');
         $params->setBasicSearch($query->getString(), $query->getHandler());
         $request = $this->createMock(\Laminas\Stdlib\Parameters::class);
 
@@ -271,9 +273,8 @@ class RandomRecommendTest extends TestCase
      *
      * @return mixed
      */
-    protected function getFixture($file)
+    protected function unserializeFixture($file)
     {
-        $fixturePath = realpath(__DIR__ . '/../../../../fixtures/searches/basic') . '/';
-        return unserialize(file_get_contents($fixturePath . $file));
+        return unserialize($this->getFixture("searches/basic/$file"));
     }
 }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/DefaultRecordTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/DefaultRecordTest.php
index f38ffa8366d520ca9df6304756ccc8554e5d37f1..1462014a01a620d59803496a285efd0a1eb7bfc9 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/DefaultRecordTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/DefaultRecordTest.php
@@ -44,6 +44,8 @@ use VuFind\RecordDriver\Response\PublicationDetails;
  */
 class DefaultRecordTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test getPublicationDates for a record.
      *
@@ -431,15 +433,7 @@ class DefaultRecordTest extends \VuFindTest\Unit\TestCase
      */
     protected function getDriver($overrides = [], Config $mainConfig = null)
     {
-        $fixture = json_decode(
-            file_get_contents(
-                realpath(
-                    VUFIND_PHPUNIT_MODULE_PATH . '/fixtures/misc/testbug2.json'
-                )
-            ),
-            true
-        );
-
+        $fixture = $this->getJsonFixture('misc/testbug2.json');
         $record = new DefaultRecord($mainConfig);
         $record->setRawData($overrides + $fixture['response']['docs'][0]);
         return $record;
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrDefaultTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrDefaultTest.php
index 6c341a8e376705c8ff23851ab28a83220d5bd130..decfa84ce318471a3a0e3adabdfcb4d807cc8bcd 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrDefaultTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrDefaultTest.php
@@ -43,6 +43,8 @@ use VuFind\RecordDriver\SolrDefault;
  */
 class SolrDefaultTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test an OpenURL for a book.
      *
@@ -202,15 +204,7 @@ XML;
      */
     protected function getDriver($overrides = [], $searchConfig = [])
     {
-        $fixture = json_decode(
-            file_get_contents(
-                realpath(
-                    VUFIND_PHPUNIT_MODULE_PATH . '/fixtures/misc/testbug2.json'
-                )
-            ),
-            true
-        );
-
+        $fixture = $this->getJsonFixture('misc/testbug2.json');
         $record = new SolrDefault(null, null, new \Laminas\Config\Config($searchConfig));
         $record->setRawData($overrides + $fixture['response']['docs'][0]);
         return $record;
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrMarcTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrMarcTest.php
index d2acb344e368b21144f38e33e2dbdf20cbe78ada..dfb65debf618e305dcbe813fc9ff358243bd8cf4 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrMarcTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrMarcTest.php
@@ -41,6 +41,8 @@ namespace VuFindTest\RecordDriver;
  */
 class SolrMarcTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test a record that used to be known to cause problems because of the way
      * its linking fields are set up.
@@ -56,7 +58,7 @@ class SolrMarcTest extends \VuFindTest\Unit\TestCase
         $configArr = ['Record' => ['marc_links' => '760,765,770,772,774,773,775,777,780,785']];
         $config = new \Laminas\Config\Config($configArr);
         $record = new \VuFind\RecordDriver\SolrMarc($config);
-        $fixture = $this->loadRecordFixture('testbug1.json');
+        $fixture = $this->getJsonFixture('misc/testbug1.json');
         $record->setRawData($fixture['response']['docs'][0]);
         $expected = [
             ['title' => 'A', 'value' => 'Bollettino della Unione matematica italiana', 'link' => ['type' => 'bib', 'value' => '000343528']],
@@ -75,7 +77,7 @@ class SolrMarcTest extends \VuFindTest\Unit\TestCase
     public function testBug2()
     {
         $record = new \VuFind\RecordDriver\SolrMarc();
-        $fixture = $this->loadRecordFixture('testbug2.json');
+        $fixture = $this->getJsonFixture('misc/testbug2.json');
         $record->setRawData($fixture['response']['docs'][0]);
 
         $this->assertEquals(
@@ -102,7 +104,7 @@ class SolrMarcTest extends \VuFindTest\Unit\TestCase
     {
         $config = new \Laminas\Config\Config([]);
         $record = new \VuFind\RecordDriver\SolrMarc($config);
-        $fixture = $this->loadRecordFixture('testbug1.json');
+        $fixture = $this->getJsonFixture('misc/testbug1.json');
         $record->setRawData($fixture['response']['docs'][0]);
         $this->assertEquals(
             [['Matematica', 'Periodici.']],
@@ -129,7 +131,7 @@ class SolrMarcTest extends \VuFindTest\Unit\TestCase
     {
         $config = new \Laminas\Config\Config([]);
         $record = new \VuFind\RecordDriver\SolrMarc($config);
-        $fixture = $this->loadRecordFixture('testbug1.json');
+        $fixture = $this->getJsonFixture('misc/testbug1.json');
         $record->setRawData($fixture['response']['docs'][0]);
         $input = [
             'foo' => 'msg|true',
@@ -158,23 +160,4 @@ class SolrMarcTest extends \VuFindTest\Unit\TestCase
             $record->getFormattedMarcDetails('245', $input)
         );
     }
-
-    /**
-     * Load a fixture file.
-     *
-     * @param string $file File to load from fixture directory.
-     *
-     * @return array
-     */
-    protected function loadRecordFixture($file)
-    {
-        return json_decode(
-            file_get_contents(
-                realpath(
-                    VUFIND_PHPUNIT_MODULE_PATH . '/fixtures/misc/' . $file
-                )
-            ),
-            true
-        );
-    }
 }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Reserves/CsvReaderTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Reserves/CsvReaderTest.php
index 707a0ef5e3578af2d84049dd0a57fce81f2c776c..2af4d0cd84bedbb8940f1936738adcc9d4540a90 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Reserves/CsvReaderTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Reserves/CsvReaderTest.php
@@ -40,6 +40,8 @@ use VuFind\Reserves\CsvReader;
  */
 class CsvReaderTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test getInstructors()
      *
@@ -127,7 +129,7 @@ class CsvReaderTest extends \VuFindTest\Unit\TestCase
     {
         $reader = $this->getReader();
         $reader->getReserves();
-        $fixture = $this->getFixturePath('reserves.csv');
+        $fixture = $this->getFixtureDir() . "reserves/reserves.csv";
         $errors = "Skipping empty/missing Bib ID: $fixture, line 3\nSkipping incomplete row: $fixture, line 5\n";
         $this->assertEquals($errors, $reader->getErrors());
     }
@@ -154,18 +156,6 @@ class CsvReaderTest extends \VuFindTest\Unit\TestCase
      */
     protected function getReader($fixture = 'reserves.csv')
     {
-        return new CsvReader($this->getFixturePath($fixture));
-    }
-
-    /**
-     * Get a fixture path
-     *
-     * @param string $fixture Name of file to load
-     *
-     * @return string
-     */
-    protected function getFixturePath($fixture)
-    {
-        return realpath(__DIR__ . '/../../../../fixtures/reserves/' . $fixture);
+        return new CsvReader($this->getFixtureDir() . "reserves/$fixture");
     }
 }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Resolver/Driver/AlmaTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Resolver/Driver/AlmaTest.php
index 636ac0f0c184a6e2348eff70f5fd045148e4bf6d..53b11a3c5e6904bb018343b463c39483043c3728 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Resolver/Driver/AlmaTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Resolver/Driver/AlmaTest.php
@@ -50,6 +50,8 @@ use VuFind\Resolver\Driver\Alma;
  */
 class AlmaTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test-Config
      *
@@ -172,17 +174,9 @@ class AlmaTest extends \VuFindTest\Unit\TestCase
     {
         $adapter = new TestAdapter();
         if ($fixture) {
-            $file = realpath(
-                __DIR__ .
-                '/../../../../../../tests/fixtures/resolver/response/' . $fixture
+            $responseObj = HttpResponse::fromString(
+                $this->getFixture("resolver/response/$fixture")
             );
-            if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-                throw new InvalidArgumentException(
-                    sprintf('Unable to load fixture file: %s ', $file)
-                );
-            }
-            $response = file_get_contents($file);
-            $responseObj = HttpResponse::fromString($response);
             $adapter->setResponse($responseObj);
         }
         $_SERVER['REMOTE_ADDR'] = "127.0.0.1";
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Resolver/Driver/EzbTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Resolver/Driver/EzbTest.php
index 5bcccd54feb3e58d6ce1dc20d9c43f70a221e4ac..b3b114185a4e7e1c747c7af0e818a073e7d3baf7 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Resolver/Driver/EzbTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Resolver/Driver/EzbTest.php
@@ -47,6 +47,8 @@ use VuFind\Resolver\Driver\Ezb;
  */
 class EzbTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test-Config
      *
@@ -163,17 +165,9 @@ class EzbTest extends \VuFindTest\Unit\TestCase
     {
         $adapter = new TestAdapter();
         if ($fixture) {
-            $file = realpath(
-                __DIR__ .
-                '/../../../../../../tests/fixtures/resolver/response/' . $fixture
+            $responseObj = HttpResponse::fromString(
+                $this->getFixture("resolver/response/$fixture")
             );
-            if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-                throw new InvalidArgumentException(
-                    sprintf('Unable to load fixture file: %s ', $file)
-                );
-            }
-            $response = file_get_contents($file);
-            $responseObj = HttpResponse::fromString($response);
             $adapter->setResponse($responseObj);
         }
         $client = new \Laminas\Http\Client();
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Resolver/Driver/RediTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Resolver/Driver/RediTest.php
index 820c9a28ac5277152759212af7fff01967f155b5..01cec8fff44400c8a2868872c4c52339e1de7416 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Resolver/Driver/RediTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Resolver/Driver/RediTest.php
@@ -47,6 +47,8 @@ use VuFind\Resolver\Driver\Redi;
  */
 class RediTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test-Config
      *
@@ -117,17 +119,9 @@ class RediTest extends \VuFindTest\Unit\TestCase
     {
         $adapter = new TestAdapter();
         if ($fixture) {
-            $file = realpath(
-                __DIR__ .
-                '/../../../../../../tests/fixtures/resolver/response/' . $fixture
+            $responseObj = HttpResponse::fromString(
+                $this->getFixture("resolver/response/$fixture")
             );
-            if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-                throw new InvalidArgumentException(
-                    sprintf('Unable to load fixture file: %s ', $file)
-                );
-            }
-            $response = file_get_contents($file);
-            $responseObj = HttpResponse::fromString($response);
             $adapter->setResponse($responseObj);
         }
         $client = new \Laminas\Http\Client();
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/QueryAdapterTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/QueryAdapterTest.php
index 8d9cc083fa779e7324f9390eb6793e7557aea544..9e3c1313c52be52d626f51cd4d809dd7692cf091 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/QueryAdapterTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/QueryAdapterTest.php
@@ -43,6 +43,8 @@ use VuFindTest\Unit\TestCase as TestCase;
  */
 class QueryAdapterTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test various conversions.
      *
@@ -51,11 +53,10 @@ class QueryAdapterTest extends TestCase
     public function testConversions()
     {
         $cases = ['basic', 'advanced'];
-        $fixturePath = realpath(__DIR__ . '/../../../../fixtures/searches') . '/';
         foreach ($cases as $case) {
             // Load minified, unminified, and Query object data:
-            $min = unserialize(file_get_contents($fixturePath . $case . '/min'));
-            $q = unserialize(file_get_contents($fixturePath . $case . '/query'));
+            $min = unserialize($this->getFixture('searches/' . $case . '/min'));
+            $q = unserialize($this->getFixture('searches/' . $case . '/query'));
 
             // Test conversion of minified data:
             $this->assertEquals($q, QueryAdapter::deminify($min));
@@ -75,8 +76,7 @@ class QueryAdapterTest extends TestCase
      */
     public function testOperatorDefinedEverywhere()
     {
-        $fixturePath = realpath(__DIR__ . '/../../../../fixtures/searches') . '/';
-        $q = unserialize(file_get_contents($fixturePath . '/operators'));
+        $q = unserialize($this->getFixture('searches/operators'));
         $minified = QueryAdapter::minify($q);
 
         // First, check that count of 'o' values matches count of queries in group:
@@ -102,9 +102,8 @@ class QueryAdapterTest extends TestCase
      */
     public function testAdvancedRequest()
     {
-        $fixturePath = realpath(__DIR__ . '/../../../../fixtures/searches') . '/advanced/';
-        $req = unserialize(file_get_contents($fixturePath . 'request'));
-        $q = unserialize(file_get_contents($fixturePath . 'query'));
+        $req = unserialize($this->getFixture('searches/advanced/request'));
+        $q = unserialize($this->getFixture('searches/advanced/query'));
         $this->assertEquals($q, QueryAdapter::fromRequest($req, 'AllFields'));
     }
 
@@ -138,9 +137,8 @@ class QueryAdapterTest extends TestCase
         };
 
         // Run the tests:
-        $fixturePath = realpath(__DIR__ . '/../../../../fixtures/searches') . '/';
         foreach ($cases as $case => $expected) {
-            $q = unserialize(file_get_contents($fixturePath . $case . '/query'));
+            $q = unserialize($this->getFixture('searches/' . $case . '/query'));
             $this->assertEquals($expected, QueryAdapter::display($q, $echo, $echo));
         }
     }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/SpellingProcessorTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/SpellingProcessorTest.php
index 091efc633120898bde6bfa26c2b82581301b2584..0cf5390c68844e48ce6b74cb44c7922f9d267364 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/SpellingProcessorTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/SpellingProcessorTest.php
@@ -43,6 +43,8 @@ use VuFindTest\Unit\TestCase;
  */
 class SpellingProcessorTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test defaults.
      *
@@ -76,8 +78,8 @@ class SpellingProcessorTest extends TestCase
     public function testSuggestionProcessing()
     {
         $sp = new SpellingProcessor();
-        $spelling = $this->getFixture('spell1');
-        $query = $this->getFixture('query1');
+        $spelling = $this->unserializeFixture('spell1');
+        $query = $this->unserializeFixture('query1');
         $this->assertEquals(
             $this->getExpectedQuery1Suggestions(),
             $sp->getSuggestions($spelling, $query)
@@ -93,8 +95,8 @@ class SpellingProcessorTest extends TestCase
     {
         $config = new Config(['limit' => 5]);
         $sp = new SpellingProcessor($config);
-        $spelling = $this->getFixture('spell1');
-        $query = $this->getFixture('query1');
+        $spelling = $this->unserializeFixture('spell1');
+        $query = $this->unserializeFixture('query1');
         $this->assertEquals(
             [
                 'grumble' => [
@@ -128,8 +130,8 @@ class SpellingProcessorTest extends TestCase
      */
     public function testBasicSuggestions()
     {
-        $spelling = $this->getFixture('spell1');
-        $query = $this->getFixture('query1');
+        $spelling = $this->unserializeFixture('spell1');
+        $query = $this->unserializeFixture('query1');
         $params = $this->getServiceManager()
             ->get(\VuFind\Search\Params\PluginManager::class)->get('Solr');
         $params->setBasicSearch($query->getString(), $query->getHandler());
@@ -190,8 +192,8 @@ class SpellingProcessorTest extends TestCase
      */
     public function testBasicSuggestionsForUppercaseQuery()
     {
-        $spelling = $this->getFixture('spell6');
-        $query = $this->getFixture('query6');
+        $spelling = $this->unserializeFixture('spell6');
+        $query = $this->unserializeFixture('query6');
         $params = $this->getServiceManager()
             ->get(\VuFind\Search\Params\PluginManager::class)->get('Solr');
         $params->setBasicSearch($query->getString(), $query->getHandler());
@@ -252,8 +254,8 @@ class SpellingProcessorTest extends TestCase
      */
     public function testBasicSuggestionsWithNonDefaultSettings()
     {
-        $spelling = $this->getFixture('spell1');
-        $query = $this->getFixture('query1');
+        $spelling = $this->unserializeFixture('spell1');
+        $query = $this->unserializeFixture('query1');
         $params = $this->getServiceManager()
             ->get(\VuFind\Search\Params\PluginManager::class)->get('Solr');
         $params->setBasicSearch($query->getString(), $query->getHandler());
@@ -472,8 +474,8 @@ class SpellingProcessorTest extends TestCase
         $this->expectExceptionMessage('Unexpected suggestion format; spellcheck.extendedResults must be set to true.');
 
         $sp = new SpellingProcessor(new Config([]));
-        $spelling = $this->getFixture('spell5');
-        $query = $this->getFixture('query5');
+        $spelling = $this->unserializeFixture('spell5');
+        $query = $this->unserializeFixture('query5');
         $sp->getSuggestions($spelling, $query);
     }
 
@@ -488,8 +490,8 @@ class SpellingProcessorTest extends TestCase
      */
     protected function runSpellingTest($testNum, $expected, $config = [])
     {
-        $spelling = $this->getFixture('spell' . $testNum);
-        $query = $this->getFixture('query' . $testNum);
+        $spelling = $this->unserializeFixture('spell' . $testNum);
+        $query = $this->unserializeFixture('query' . $testNum);
         $params = $this->getServiceManager()
             ->get(\VuFind\Search\Params\PluginManager::class)->get('Solr');
         $this->setProperty($params, 'query', $query);
@@ -562,9 +564,8 @@ class SpellingProcessorTest extends TestCase
      *
      * @return mixed
      */
-    protected function getFixture($file)
+    protected function unserializeFixture($file)
     {
-        $fixturePath = realpath(__DIR__ . '/../../../../../fixtures/spell') . '/';
-        return unserialize(file_get_contents($fixturePath . $file));
+        return unserialize($this->getFixture("spell/$file"));
     }
 }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/V3/ErrorListenerTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/V3/ErrorListenerTest.php
index 29350c546c1a7d4f769a3269543f9af4c4336bed..2832342e79677260af99ff09a3550157f8dc56b8 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/V3/ErrorListenerTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/V3/ErrorListenerTest.php
@@ -33,7 +33,6 @@ use Laminas\EventManager\Event;
 use Laminas\Http\Response;
 
 use PHPUnit\Framework\TestCase;
-use RuntimeException;
 
 use VuFind\Search\Solr\V3\ErrorListener;
 
@@ -50,6 +49,8 @@ use VuFindSearch\Backend\Exception\HttpErrorException;
  */
 class ErrorListenerTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Detect parser error response.
      *
@@ -97,15 +98,8 @@ class ErrorListenerTest extends TestCase
      */
     protected function createResponse($name)
     {
-        $file = realpath(
-            \VUFIND_PHPUNIT_MODULE_PATH . '/fixtures/response/solr/' . $name
+        return Response::fromString(
+            $this->getFixture('response/solr/' . $name)
         );
-        if (!$file) {
-            throw new RuntimeException(
-                sprintf('Unable to resolve fixture to fixture file: %s', $name)
-            );
-        }
-        $response = Response::fromString(file_get_contents($file));
-        return $response;
     }
 }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/V4/ErrorListenerTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/V4/ErrorListenerTest.php
index e4ce4aed287bd3211399b8c0db440a9fa273d73f..84496917c80ed188d37f1e4652194250539f4b8e 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/V4/ErrorListenerTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/V4/ErrorListenerTest.php
@@ -33,7 +33,6 @@ use Laminas\EventManager\Event;
 use Laminas\Http\Response;
 
 use PHPUnit\Framework\TestCase;
-use RuntimeException;
 
 use VuFind\Search\Solr\V4\ErrorListener;
 
@@ -50,6 +49,8 @@ use VuFindSearch\Backend\Exception\HttpErrorException;
  */
 class ErrorListenerTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Detect parser error response.
      *
@@ -97,15 +98,8 @@ class ErrorListenerTest extends TestCase
      */
     protected function createResponse($name)
     {
-        $file = realpath(
-            \VUFIND_PHPUNIT_MODULE_PATH . '/fixtures/response/solr/' . $name
+        return Response::fromString(
+            $this->getFixture('response/solr/' . $name)
         );
-        if (!$file) {
-            throw new RuntimeException(
-                sprintf('Unable to resolve fixture to fixture file: %s', $name)
-            );
-        }
-        $response = Response::fromString(file_get_contents($file));
-        return $response;
     }
 }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/UrlQueryHelperTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/UrlQueryHelperTest.php
index b3f59b0fa3e2b57d16738419d34b8938798eff30..cc8a95a7c7319070e814c0d57616e8d7667eca17 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/UrlQueryHelperTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/UrlQueryHelperTest.php
@@ -44,6 +44,8 @@ use VuFindTest\Unit\TestCase as TestCase;
  */
 class UrlQueryHelperTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Get a preconfigured helper.
      *
@@ -195,8 +197,7 @@ class UrlQueryHelperTest extends TestCase
      */
     public function testAdvancedSearch()
     {
-        $fixturePath = realpath(__DIR__ . '/../../../../fixtures/searches') . '/advanced/';
-        $q = unserialize(file_get_contents($fixturePath . 'query'));
+        $q = unserialize($this->getFixture('searches/advanced/query'));
         $helper = new UrlQueryHelper([], $q);
         $this->assertEquals(
             '?join=OR&bool0%5B%5D=AND&lookfor0%5B%5D=oranges&lookfor0%5B%5D=bananas'
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/OpenUrlTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/OpenUrlTest.php
index ebc256be7fe49817b34cec32f604d21951fe6f2e..f818ea86650eb2fb266035799d202d998caab030 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/OpenUrlTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/OpenUrlTest.php
@@ -43,6 +43,8 @@ use VuFind\View\Helper\Root\OpenUrl;
  */
 class OpenUrlTest extends \VuFindTest\Unit\ViewHelperTestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Configuration array providing basic settings for testing OpenUrlRules
      *
@@ -112,7 +114,7 @@ class OpenUrlTest extends \VuFindTest\Unit\ViewHelperTestCase
     public function testCheckExcludedRecordsRulesFalse()
     {
         $openUrl = $this
-            ->getOpenUrl($this->getFixture("rule1.json"), $this->rulesConfig)
+            ->getOpenUrl($this->getJsonFixture("openurlrules/rule1.json"), $this->rulesConfig)
             ->__invoke($this->getMockDriver(), 'results');
         $this->assertTrue($openUrl->isActive());
     }
@@ -126,7 +128,7 @@ class OpenUrlTest extends \VuFindTest\Unit\ViewHelperTestCase
     public function testCheckExcludedRecordsRulesTrue()
     {
         $openUrl = $this
-            ->getOpenUrl($this->getFixture("rule2.json"), $this->rulesConfig)
+            ->getOpenUrl($this->getJsonFixture("openurlrules/rule2.json"), $this->rulesConfig)
             ->__invoke($this->getMockDriver(), 'results');
         $this->assertFalse($openUrl->isActive());
     }
@@ -144,7 +146,7 @@ class OpenUrlTest extends \VuFindTest\Unit\ViewHelperTestCase
             'fake-data', 'VuFind\RecordDriver\SolrMarc', ['Article'], false
         );
         $openUrl = $this
-            ->getOpenUrl($this->getFixture("rule5.json"), $this->rulesConfig)
+            ->getOpenUrl($this->getJsonFixture("openurlrules/rule5.json"), $this->rulesConfig)
             ->__invoke($driver, 'results');
         $this->assertFalse($openUrl->isActive());
     }
@@ -158,7 +160,7 @@ class OpenUrlTest extends \VuFindTest\Unit\ViewHelperTestCase
     public function testCheckSupportedRecordsRulesFalse()
     {
         $openUrl = $this
-            ->getOpenUrl($this->getFixture("rule3.json"), $this->rulesConfig)
+            ->getOpenUrl($this->getJsonFixture("openurlrules/rule3.json"), $this->rulesConfig)
             ->__invoke($this->getMockDriver(), 'results');
         $this->assertFalse($openUrl->isActive());
     }
@@ -176,7 +178,7 @@ class OpenUrlTest extends \VuFindTest\Unit\ViewHelperTestCase
             'fake-openurl', 'VuFind\RecordDriver\SolrDefault', ['CrazyFormat']
         );
         $openUrl = $this
-            ->getOpenUrl($this->getFixture("rule5.json"), $this->rulesConfig)
+            ->getOpenUrl($this->getJsonFixture("openurlrules/rule5.json"), $this->rulesConfig)
             ->__invoke($driver, 'results');
         $this->assertFalse($openUrl->isActive());
     }
@@ -190,7 +192,7 @@ class OpenUrlTest extends \VuFindTest\Unit\ViewHelperTestCase
     public function testCheckSupportedRecordsRulesTrue()
     {
         $openUrl = $this
-            ->getOpenUrl($this->getFixture("rule4.json"), $this->rulesConfig)
+            ->getOpenUrl($this->getJsonFixture("openurlrules/rule4.json"), $this->rulesConfig)
             ->__invoke($this->getMockDriver(), 'results');
         $this->assertTrue($openUrl->isActive());
     }
@@ -211,7 +213,7 @@ class OpenUrlTest extends \VuFindTest\Unit\ViewHelperTestCase
             'fake-data', 'VuFind\RecordDriver\SolrMarc', $formats
         );
         $openUrl = $this
-            ->getOpenUrl($this->getFixture("rule1.json"), $this->rulesConfig);
+            ->getOpenUrl($this->getJsonFixture("openurlrules/rule1.json"), $this->rulesConfig);
         $this->assertTrue($openUrl->__invoke($defaultDriver, 'results')->isActive());
         $this->assertFalse($openUrl->__invoke($marcDriver, 'results')->isActive());
     }
@@ -253,31 +255,6 @@ class OpenUrlTest extends \VuFindTest\Unit\ViewHelperTestCase
         return $driver;
     }
 
-    /**
-     * Get the fixtures for testing OpenUrlRules
-     *
-     * @param string $fixture filename of the fixture to load
-     *
-     * @return mixed|null
-     */
-    protected function getFixture($fixture)
-    {
-        if ($fixture) {
-            $file = realpath(
-                __DIR__ .
-                '/../../../../../../../tests/fixtures/openurlrules/' . $fixture
-            );
-            if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-                throw new \InvalidArgumentException(
-                    sprintf('Unable to load fixture file: %s ', $fixture)
-                );
-            }
-            return json_decode(file_get_contents($file), true);
-        }
-
-        return null;
-    }
-
     /**
      * Get the object to test
      *
@@ -290,7 +267,7 @@ class OpenUrlTest extends \VuFindTest\Unit\ViewHelperTestCase
     protected function getOpenUrl($rules = null, $config = [], $mockContext = null)
     {
         if (null === $rules) {
-            $rules = $this->getFixture('defaults.json');
+            $rules = $this->getJsonFixture('openurlrules/defaults.json');
         }
         if (null === $mockContext) {
             $mockContext = $this->getMockContext();
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordDataFormatterTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordDataFormatterTest.php
index 275dccaccffff974af61056f1f08028d6c995ec2..2ef69a00557731b994e56e127add7814ebbbdf1c 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordDataFormatterTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordDataFormatterTest.php
@@ -41,6 +41,8 @@ use VuFind\View\Helper\Root\RecordDataFormatterFactory;
  */
 class RecordDataFormatterTest extends \VuFindTest\Unit\ViewHelperTestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Get a mock record router.
      *
@@ -119,14 +121,7 @@ class RecordDataFormatterTest extends \VuFindTest\Unit\ViewHelperTestCase
             ->will($this->returnValue($authors));
 
         // Load record data from fixture file:
-        $fixture = json_decode(
-            file_get_contents(
-                realpath(
-                    VUFIND_PHPUNIT_MODULE_PATH . '/fixtures/misc/testbug2.json'
-                )
-            ),
-            true
-        );
+        $fixture = $this->getJsonFixture('misc/testbug2.json');
         $record->setRawData($overrides + $fixture['response']['docs'][0]);
         return $record;
     }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordTest.php
index ab44fbde88484ffa891eed77cb64e8b0ef9ee613..a3c8f9452f1c532d81c62956d8e1a648c757a499 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordTest.php
@@ -44,6 +44,8 @@ use VuFindTheme\ThemeInfo;
  */
 class RecordTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Theme to use for testing purposes.
      *
@@ -616,14 +618,7 @@ class RecordTest extends \PHPUnit\Framework\TestCase
      */
     protected function loadRecordFixture($file)
     {
-        $json = json_decode(
-            file_get_contents(
-                realpath(
-                    VUFIND_PHPUNIT_MODULE_PATH . '/fixtures/misc/' . $file
-                )
-            ),
-            true
-        );
+        $json = $this->getJsonFixture('misc/' . $file);
         $record = new \VuFind\RecordDriver\SolrMarc();
         $record->setRawData($json['response']['docs'][0]);
         return $record;
diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/DynamicRouteCommandTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/DynamicRouteCommandTest.php
index 3ebd1bb36d030ec27cfa65a3d6426c6938689c48..b75a9935bf66f0194659523a119814fd95daa31e 100644
--- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/DynamicRouteCommandTest.php
+++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/DynamicRouteCommandTest.php
@@ -44,6 +44,8 @@ use VuFindConsole\Generator\GeneratorTools;
  */
 class DynamicRouteCommandTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test that missing parameters yield an error message.
      *
@@ -73,7 +75,7 @@ class DynamicRouteCommandTest extends \PHPUnit\Framework\TestCase
      */
     public function testSuccessWithMinimalParameters()
     {
-        $configFixturePath = __DIR__ . '/../../../../../fixtures/empty.config.php';
+        $configFixturePath = $this->getFixtureDir('VuFindConsole') . 'empty.config.php';
         $expectedConfig = include $configFixturePath;
         $tools = $this->getMockGeneratorTools(
             ['getModuleConfigPath', 'backUpFile', 'writeModuleConfig']
diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/NonTabRecordActionCommandTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/NonTabRecordActionCommandTest.php
index 8ff33dd71faba76b8e8447f9e477893c3741eb26..4befb3e8b4b6b9bbdf3e481b30d19e26dccf6b08 100644
--- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/NonTabRecordActionCommandTest.php
+++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/NonTabRecordActionCommandTest.php
@@ -42,6 +42,8 @@ use VuFindConsole\Generator\GeneratorTools;
  */
 class NonTabRecordActionCommandTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test that missing parameters yield an error message.
      *
@@ -71,7 +73,7 @@ class NonTabRecordActionCommandTest extends \PHPUnit\Framework\TestCase
      */
     public function testSuccessWithMinimalParameters()
     {
-        $configFixturePath = __DIR__ . '/../../../../../fixtures/empty.config.php';
+        $configFixturePath = $this->getFixtureDir('VuFindConsole') . 'empty.config.php';
         $expectedConfig = [
             'router' => [
                 'routes' => [
diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/RecordRouteCommandTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/RecordRouteCommandTest.php
index e58e1fb7cc044c7c8c172596570a98645dd34ab6..20955bd9619768e7ca12b9947e399854bd524ef2 100644
--- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/RecordRouteCommandTest.php
+++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/RecordRouteCommandTest.php
@@ -44,6 +44,8 @@ use VuFindConsole\Generator\GeneratorTools;
  */
 class RecordRouteCommandTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test that missing parameters yield an error message.
      *
@@ -73,7 +75,7 @@ class RecordRouteCommandTest extends \PHPUnit\Framework\TestCase
      */
     public function testSuccessWithMinimalParameters()
     {
-        $configFixturePath = __DIR__ . '/../../../../../fixtures/empty.config.php';
+        $configFixturePath = $this->getFixtureDir('VuFindConsole') . 'empty.config.php';
         $expectedConfig = include $configFixturePath;
         $tools = $this->getMockGeneratorTools(
             ['getModuleConfigPath', 'backUpFile', 'writeModuleConfig']
diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/StaticRouteCommandTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/StaticRouteCommandTest.php
index e8fa0dfd0de07a7ddd83cd85e356af2081cf1cd4..c91eb79860f19f2103fcbb9651c22a9be436128a 100644
--- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/StaticRouteCommandTest.php
+++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Generate/StaticRouteCommandTest.php
@@ -44,6 +44,8 @@ use VuFindConsole\Generator\GeneratorTools;
  */
 class StaticRouteCommandTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test that missing parameters yield an error message.
      *
@@ -73,7 +75,7 @@ class StaticRouteCommandTest extends \PHPUnit\Framework\TestCase
      */
     public function testSuccessWithMinimalParameters()
     {
-        $configFixturePath = __DIR__ . '/../../../../../fixtures/empty.config.php';
+        $configFixturePath = $this->getFixtureDir('VuFindConsole') . 'empty.config.php';
         $expectedConfig = include $configFixturePath;
         $tools = $this->getMockGeneratorTools(
             ['getModuleConfigPath', 'backUpFile', 'writeModuleConfig']
diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Harvest/MergeMarcCommandTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Harvest/MergeMarcCommandTest.php
index 284892bedc4fb4b30e35f11df344c2867bc9667a..444f6b582f84dcd542d7122424250ae798dc32ca 100644
--- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Harvest/MergeMarcCommandTest.php
+++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Harvest/MergeMarcCommandTest.php
@@ -41,6 +41,8 @@ use VuFindConsole\Command\Harvest\MergeMarcCommand;
  */
 class MergeMarcCommandTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test that missing parameters yield an error message.
      *
@@ -68,7 +70,7 @@ class MergeMarcCommandTest extends \PHPUnit\Framework\TestCase
     {
         $command = new MergeMarcCommand();
         $commandTester = new CommandTester($command);
-        $directory = __DIR__ . '/../../../../../fixtures/xml';
+        $directory = $this->getFixtureDir('VuFindConsole') . 'xml';
         $commandTester->execute(compact('directory'));
         $expected = <<<EXPECTED
 <collection>
@@ -92,7 +94,7 @@ EXPECTED;
     {
         $command = new MergeMarcCommand();
         $commandTester = new CommandTester($command);
-        $directory = __DIR__ . '/../../../../../fixtures/does-not-exist';
+        $directory = $this->getFixtureDir('VuFindConsole') . 'does-not-exist';
         $commandTester->execute(compact('directory'));
         $expected = "Cannot open directory: $directory\n";
         $this->assertEquals($expected, $commandTester->getDisplay());
diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Import/WebCrawlCommandTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Import/WebCrawlCommandTest.php
index 165cf6a7010908304779f7f9adc5b3277eae70b4..65bcfb541a50b848ffd3ee37a08f585687ecee15 100644
--- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Import/WebCrawlCommandTest.php
+++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Import/WebCrawlCommandTest.php
@@ -44,6 +44,8 @@ use VuFindConsole\Command\Import\WebCrawlCommand;
  */
 class WebCrawlCommandTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test the simplest possible success case.
      *
@@ -51,8 +53,8 @@ class WebCrawlCommandTest extends \PHPUnit\Framework\TestCase
      */
     public function testSuccessWithMinimalParameters()
     {
-        $fixture1 = __DIR__ . '/../../../../../fixtures/sitemap/index.xml';
-        $fixture2 = __DIR__ . '/../../../../../fixtures/sitemap/map.xml';
+        $fixture1 = $this->getFixtureDir('VuFindConsole') . 'sitemap/index.xml';
+        $fixture2 = $this->getFixtureDir('VuFindConsole') . 'sitemap/map.xml';
         $importer = $this->getMockImporter();
         $importer->expects($this->once())->method('save')
             ->with(
diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/AddUsingTemplateCommandTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/AddUsingTemplateCommandTest.php
index 5a6edb549d450cb7959d03f8005c5de9a671cf6c..3f643f32c587ec8a6af389d2fde8ad727d0b0ee1 100644
--- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/AddUsingTemplateCommandTest.php
+++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/AddUsingTemplateCommandTest.php
@@ -43,12 +43,24 @@ use VuFindConsole\Command\Language\AddUsingTemplateCommand;
  */
 class AddUsingTemplateCommandTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Language fixture directory
      *
      * @var string
      */
-    protected $languageFixtureDir = __DIR__ . '/../../../../../fixtures/language';
+    protected $languageFixtureDir = null;
+
+    /**
+     * Standard setup method.
+     *
+     * @return void
+     */
+    public function setUp(): void
+    {
+        $this->languageFixtureDir = $this->getFixtureDir('VuFindConsole') . 'language';
+    }
 
     /**
      * Test that missing parameters yield an error message.
diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/CopyStringCommandTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/CopyStringCommandTest.php
index c7fab3cace62430a65fc87d1b5d3c85396cb8426..efd57af1e2c002f49cab54e4aab94a4228bb0be2 100644
--- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/CopyStringCommandTest.php
+++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/CopyStringCommandTest.php
@@ -43,12 +43,24 @@ use VuFindConsole\Command\Language\CopyStringCommand;
  */
 class CopyStringCommandTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Language fixture directory
      *
      * @var string
      */
-    protected $languageFixtureDir = __DIR__ . '/../../../../../fixtures/language';
+    protected $languageFixtureDir = null;
+
+    /**
+     * Standard setup method.
+     *
+     * @return void
+     */
+    public function setUp(): void
+    {
+        $this->languageFixtureDir = $this->getFixtureDir('VuFindConsole') . 'language';
+    }
 
     /**
      * Test that missing parameters yield an error message.
diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/DeleteCommandTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/DeleteCommandTest.php
index 1a560dc93dfcd6755aec4c32fd71c0a088560773..e83ca5ae86d216d74d08c997d451f720d3063afe 100644
--- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/DeleteCommandTest.php
+++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/DeleteCommandTest.php
@@ -43,12 +43,24 @@ use VuFindConsole\Command\Language\DeleteCommand;
  */
 class DeleteCommandTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Language fixture directory
      *
      * @var string
      */
-    protected $languageFixtureDir = __DIR__ . '/../../../../../fixtures/language';
+    protected $languageFixtureDir = null;
+
+    /**
+     * Standard setup method.
+     *
+     * @return void
+     */
+    public function setUp(): void
+    {
+        $this->languageFixtureDir = $this->getFixtureDir('VuFindConsole') . 'language';
+    }
 
     /**
      * Test that missing parameters yield an error message.
diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/NormalizeCommandTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/NormalizeCommandTest.php
index c7350f0082b73b2aadffc29936613b0524aebfe4..6fa985d02284f21bc7a62d2cf29f12b700202548 100644
--- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/NormalizeCommandTest.php
+++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/NormalizeCommandTest.php
@@ -43,12 +43,24 @@ use VuFindConsole\Command\Language\NormalizeCommand;
  */
 class NormalizeCommandTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Language fixture directory
      *
      * @var string
      */
-    protected $languageFixtureDir = __DIR__ . '/../../../../../fixtures/language';
+    protected $languageFixtureDir = null;
+
+    /**
+     * Standard setup method.
+     *
+     * @return void
+     */
+    public function setUp(): void
+    {
+        $this->languageFixtureDir = $this->getFixtureDir('VuFindConsole') . 'language';
+    }
 
     /**
      * Test that missing parameters yield an error message.
diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/DedupeCommandTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/DedupeCommandTest.php
index f5f6aa4c0c72627b775b64099f297cd9fdd6002b..906a6b7d2d83169088cdbd31458ec2ce1b13d30c 100644
--- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/DedupeCommandTest.php
+++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/DedupeCommandTest.php
@@ -43,6 +43,8 @@ use VuFindConsole\Command\Util\DedupeCommand;
  */
 class DedupeCommandTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Get a mocked-out command object.
      *
@@ -114,7 +116,7 @@ class DedupeCommandTest extends \PHPUnit\Framework\TestCase
         $command = $this->getMockCommand();
         $this->setSuccessfulExpectations($command, $outputFilename);
         $commandTester = new CommandTester($command);
-        $fixture = __DIR__ . '/../../../../../fixtures/fileWithDuplicateLines';
+        $fixture = $this->getFixtureDir('VuFindConsole') . 'fileWithDuplicateLines';
         $commandTester->execute(
             [
                 'input' => $fixture,
@@ -132,7 +134,7 @@ class DedupeCommandTest extends \PHPUnit\Framework\TestCase
      */
     public function testSuccessWithoutArguments()
     {
-        $fixture = __DIR__ . '/../../../../../fixtures/fileWithDuplicateLines';
+        $fixture = $this->getFixtureDir('VuFindConsole') . 'fileWithDuplicateLines';
         $outputFilename = '/fake/outfile';
         $command = $this->getMockCommand();
         $command->expects($this->at(0))->method('getInput')
diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/DeletesCommandTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/DeletesCommandTest.php
index 6044aec354b54d87203759fb655c4d937fcda1ba..a65b5da74c269a3dacd2019665e5e38dbaec179a 100644
--- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/DeletesCommandTest.php
+++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/DeletesCommandTest.php
@@ -41,6 +41,8 @@ use VuFindConsole\Command\Util\DeletesCommand;
  */
 class DeletesCommandTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Get mock Solr writer.
      *
@@ -101,7 +103,7 @@ class DeletesCommandTest extends \PHPUnit\Framework\TestCase
             ->with($this->equalTo('Solr'), $this->equalTo(['rec1', 'rec2', 'rec3']));
         $command = new DeletesCommand($writer);
         $commandTester = new CommandTester($command);
-        $fixture = __DIR__ . '/../../../../../fixtures/deletes';
+        $fixture = $this->getFixtureDir('VuFindConsole') . 'deletes';
         $commandTester->execute(
             [
                 'filename' => $fixture,
diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/IndexReservesCommandTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/IndexReservesCommandTest.php
index 26bcff0c3082a67d002c58def563b063fb121ae3..34c8f5fb94e5f2a2ae3c27a7135b76ec0d29b710 100644
--- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/IndexReservesCommandTest.php
+++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/IndexReservesCommandTest.php
@@ -43,6 +43,8 @@ use VuFindConsole\Command\Util\IndexReservesCommand;
  */
 class IndexReservesCommandTest extends \PHPUnit\Framework\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Get mock ILS connection.
      *
@@ -176,8 +178,8 @@ class IndexReservesCommandTest extends \PHPUnit\Framework\TestCase
             ->with($this->equalTo('SolrReserves'));
         $command = $this->getCommand($writer);
         $commandTester = new CommandTester($command);
-        $fixture1 = __DIR__ . '/../../../../../fixtures/reserves/fixture1';
-        $fixture2 = __DIR__ . '/../../../../../fixtures/reserves/fixture2';
+        $fixture1 = $this->getFixtureDir('VuFindConsole') . 'reserves/fixture1';
+        $fixture2 = $this->getFixtureDir('VuFindConsole') . 'reserves/fixture2';
         $commandTester->execute(
             [
                 '--filename' => [$fixture1, $fixture2],
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/browzine/response/search b/module/VuFindSearch/tests/fixtures/browzine/response/search
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/browzine/response/search
rename to module/VuFindSearch/tests/fixtures/browzine/response/search
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/eds/query/advanced b/module/VuFindSearch/tests/fixtures/eds/query/advanced
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/eds/query/advanced
rename to module/VuFindSearch/tests/fixtures/eds/query/advanced
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/eds/response/autocomplete b/module/VuFindSearch/tests/fixtures/eds/response/autocomplete
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/eds/response/autocomplete
rename to module/VuFindSearch/tests/fixtures/eds/response/autocomplete
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/eds/response/retrieve b/module/VuFindSearch/tests/fixtures/eds/response/retrieve
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/eds/response/retrieve
rename to module/VuFindSearch/tests/fixtures/eds/response/retrieve
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/eds/response/search b/module/VuFindSearch/tests/fixtures/eds/response/search
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/eds/response/search
rename to module/VuFindSearch/tests/fixtures/eds/response/search
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/eit/query/advanced b/module/VuFindSearch/tests/fixtures/eit/query/advanced
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/eit/query/advanced
rename to module/VuFindSearch/tests/fixtures/eit/query/advanced
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/eit/response/retrieve b/module/VuFindSearch/tests/fixtures/eit/response/retrieve
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/eit/response/retrieve
rename to module/VuFindSearch/tests/fixtures/eit/response/retrieve
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/eit/response/search b/module/VuFindSearch/tests/fixtures/eit/response/search
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/eit/response/search
rename to module/VuFindSearch/tests/fixtures/eit/response/search
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/libguides/response/search b/module/VuFindSearch/tests/fixtures/libguides/response/search
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/libguides/response/search
rename to module/VuFindSearch/tests/fixtures/libguides/response/search
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/pazpar2/response/pp2search b/module/VuFindSearch/tests/fixtures/pazpar2/response/pp2search
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/pazpar2/response/pp2search
rename to module/VuFindSearch/tests/fixtures/pazpar2/response/pp2search
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/pazpar2/response/pp2show b/module/VuFindSearch/tests/fixtures/pazpar2/response/pp2show
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/pazpar2/response/pp2show
rename to module/VuFindSearch/tests/fixtures/pazpar2/response/pp2show
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/primo/response/error-with-success-http b/module/VuFindSearch/tests/fixtures/primo/response/error-with-success-http
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/primo/response/error-with-success-http
rename to module/VuFindSearch/tests/fixtures/primo/response/error-with-success-http
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/primo/response/record-http b/module/VuFindSearch/tests/fixtures/primo/response/record-http
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/primo/response/record-http
rename to module/VuFindSearch/tests/fixtures/primo/response/record-http
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/primo/response/retrieve b/module/VuFindSearch/tests/fixtures/primo/response/retrieve
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/primo/response/retrieve
rename to module/VuFindSearch/tests/fixtures/primo/response/retrieve
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/primo/response/search b/module/VuFindSearch/tests/fixtures/primo/response/search
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/primo/response/search
rename to module/VuFindSearch/tests/fixtures/primo/response/search
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/primo/response/search-http b/module/VuFindSearch/tests/fixtures/primo/response/search-http
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/primo/response/search-http
rename to module/VuFindSearch/tests/fixtures/primo/response/search-http
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/primo/response/swansea-search-http b/module/VuFindSearch/tests/fixtures/primo/response/swansea-search-http
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/primo/response/swansea-search-http
rename to module/VuFindSearch/tests/fixtures/primo/response/swansea-search-http
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/searchspecs.yaml b/module/VuFindSearch/tests/fixtures/searchspecs.yaml
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/searchspecs.yaml
rename to module/VuFindSearch/tests/fixtures/searchspecs.yaml
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/bad-request b/module/VuFindSearch/tests/fixtures/solr/response/bad-request
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/solr/response/bad-request
rename to module/VuFindSearch/tests/fixtures/solr/response/bad-request
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/internal-server-error b/module/VuFindSearch/tests/fixtures/solr/response/internal-server-error
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/solr/response/internal-server-error
rename to module/VuFindSearch/tests/fixtures/solr/response/internal-server-error
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/morelikethis b/module/VuFindSearch/tests/fixtures/solr/response/morelikethis
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/solr/response/morelikethis
rename to module/VuFindSearch/tests/fixtures/solr/response/morelikethis
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/multi-record b/module/VuFindSearch/tests/fixtures/solr/response/multi-record
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/solr/response/multi-record
rename to module/VuFindSearch/tests/fixtures/solr/response/multi-record
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/multi-record-part1 b/module/VuFindSearch/tests/fixtures/solr/response/multi-record-part1
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/solr/response/multi-record-part1
rename to module/VuFindSearch/tests/fixtures/solr/response/multi-record-part1
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/multi-record-part2 b/module/VuFindSearch/tests/fixtures/solr/response/multi-record-part2
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/solr/response/multi-record-part2
rename to module/VuFindSearch/tests/fixtures/solr/response/multi-record-part2
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/multi-record-part3 b/module/VuFindSearch/tests/fixtures/solr/response/multi-record-part3
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/solr/response/multi-record-part3
rename to module/VuFindSearch/tests/fixtures/solr/response/multi-record-part3
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/no-match b/module/VuFindSearch/tests/fixtures/solr/response/no-match
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/solr/response/no-match
rename to module/VuFindSearch/tests/fixtures/solr/response/no-match
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/single-record b/module/VuFindSearch/tests/fixtures/solr/response/single-record
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/solr/response/single-record
rename to module/VuFindSearch/tests/fixtures/solr/response/single-record
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/terms b/module/VuFindSearch/tests/fixtures/solr/response/terms
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/solr/response/terms
rename to module/VuFindSearch/tests/fixtures/solr/response/terms
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/summon/query/advanced b/module/VuFindSearch/tests/fixtures/summon/query/advanced
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/summon/query/advanced
rename to module/VuFindSearch/tests/fixtures/summon/query/advanced
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/summon/query/basic b/module/VuFindSearch/tests/fixtures/summon/query/basic
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/summon/query/basic
rename to module/VuFindSearch/tests/fixtures/summon/query/basic
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/summon/response/retrieve1 b/module/VuFindSearch/tests/fixtures/summon/response/retrieve1
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/summon/response/retrieve1
rename to module/VuFindSearch/tests/fixtures/summon/response/retrieve1
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/summon/response/retrieve2 b/module/VuFindSearch/tests/fixtures/summon/response/retrieve2
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/summon/response/retrieve2
rename to module/VuFindSearch/tests/fixtures/summon/response/retrieve2
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/summon/response/search b/module/VuFindSearch/tests/fixtures/summon/response/search
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/summon/response/search
rename to module/VuFindSearch/tests/fixtures/summon/response/search
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/summon/response/single-record b/module/VuFindSearch/tests/fixtures/summon/response/single-record
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/summon/response/single-record
rename to module/VuFindSearch/tests/fixtures/summon/response/single-record
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/worldcat/query/advanced b/module/VuFindSearch/tests/fixtures/worldcat/query/advanced
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/worldcat/query/advanced
rename to module/VuFindSearch/tests/fixtures/worldcat/query/advanced
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/worldcat/query/basic b/module/VuFindSearch/tests/fixtures/worldcat/query/basic
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/worldcat/query/basic
rename to module/VuFindSearch/tests/fixtures/worldcat/query/basic
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/worldcat/response/search b/module/VuFindSearch/tests/fixtures/worldcat/response/search
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/worldcat/response/search
rename to module/VuFindSearch/tests/fixtures/worldcat/response/search
diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/worldcat/response/single-record b/module/VuFindSearch/tests/fixtures/worldcat/response/single-record
similarity index 100%
rename from module/VuFindSearch/tests/unit-tests/fixtures/worldcat/response/single-record
rename to module/VuFindSearch/tests/fixtures/worldcat/response/single-record
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/BrowZine/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/BrowZine/BackendTest.php
index c21545e13f7029b7b1cdd216d7646fbe79fb5811..df604b83b730b5b539d79755e8c2f2dc9b89f3db 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/BrowZine/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/BrowZine/BackendTest.php
@@ -28,7 +28,6 @@
  */
 namespace VuFindTest\Backend\BrowZine;
 
-use InvalidArgumentException;
 use Laminas\Http\Client\Adapter\Test as TestAdapter;
 use Laminas\Http\Client as HttpClient;
 use VuFindSearch\Backend\BrowZine\Backend;
@@ -48,6 +47,8 @@ use VuFindSearch\Query\Query;
  */
 class BackendTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test retrieving a record (not supported).
      *
@@ -140,24 +141,6 @@ class BackendTest extends \VuFindTest\Unit\TestCase
 
     /// Internal API
 
-    /**
-     * Load a response as fixture.
-     *
-     * @param string $fixture Fixture file
-     *
-     * @return mixed
-     *
-     * @throws InvalidArgumentException Fixture files does not exist
-     */
-    protected function loadResponse($fixture)
-    {
-        $file = realpath(sprintf('%s/browzine/response/%s', PHPUNIT_SEARCH_FIXTURES, $fixture));
-        if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-            throw new InvalidArgumentException(sprintf('Unable to load fixture file: %s', $fixture));
-        }
-        return file_get_contents($file);
-    }
-
     /**
      * Return connector.
      *
@@ -169,7 +152,9 @@ class BackendTest extends \VuFindTest\Unit\TestCase
     {
         $adapter = new TestAdapter();
         if ($fixture) {
-            $adapter->setResponse($this->loadResponse($fixture));
+            $adapter->setResponse(
+                $this->getFixture('browzine/response/' . $fixture, 'VuFindSearch')
+            );
         }
         $client = new HttpClient();
         $client->setAdapter($adapter);
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EDS/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EDS/BackendTest.php
index 9c3cba8ab8529606316769bfd0c55993a17cbf00..dfa7e5e72d995a2e330c87832e252f37a9e9f4e1 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EDS/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EDS/BackendTest.php
@@ -43,6 +43,8 @@ use VuFindSearch\Query\Query;
  */
 class BackendTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test performing an autocomplete
      *
@@ -208,11 +210,9 @@ class BackendTest extends \VuFindTest\Unit\TestCase
      */
     protected function loadResponse($fixture)
     {
-        $file = realpath(sprintf('%s/eds/response/%s', PHPUNIT_SEARCH_FIXTURES, $fixture));
-        if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-            throw new InvalidArgumentException(sprintf('Unable to load fixture file: %s', $fixture));
-        }
-        return unserialize(file_get_contents($file));
+        return unserialize(
+            $this->getFixture('eds/response/' . $fixture, 'VuFindSearch')
+        );
     }
 
     /**
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EDS/QueryBuilderTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EDS/QueryBuilderTest.php
index 5fc2cf24a3951837a80c35b1a0ef2e5e5b879274..86aee0c025bd817f94d1cad16a43a375a5fd46de 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EDS/QueryBuilderTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EDS/QueryBuilderTest.php
@@ -42,6 +42,8 @@ use VuFindSearch\Backend\EDS\QueryBuilder;
  */
 class QueryBuilderTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Given a response, decode the JSON query objects for easier reading.
      *
@@ -112,11 +114,7 @@ class QueryBuilderTest extends TestCase
         $qb = new QueryBuilder();
         foreach ($tests as $test) {
             list($input, $output) = $test;
-            $q = unserialize(
-                file_get_contents(
-                    PHPUNIT_SEARCH_FIXTURES . '/eds/query/' . $input
-                )
-            );
+            $q = unserialize($this->getFixture("eds/query/$input", 'VuFindSearch'));
             $response = $qb->build($q);
             $this->assertEquals(
                 $output, $this->decodeResponse($response->get('query'))
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EIT/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EIT/BackendTest.php
index de02df81e3d71760151daa335966dbd79fc0a7f4..c4fa9946d0912a710c18d9ad03342c5535ee808f 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EIT/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EIT/BackendTest.php
@@ -44,6 +44,8 @@ use VuFindSearch\Query\Query;
  */
 class BackendTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test retrieving a record.
      *
@@ -148,11 +150,7 @@ class BackendTest extends \VuFindTest\Unit\TestCase
      */
     protected function loadResponse($fixture)
     {
-        $file = realpath(sprintf('%s/eit/response/%s', PHPUNIT_SEARCH_FIXTURES, $fixture));
-        if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-            throw new InvalidArgumentException(sprintf('Unable to load fixture file: %s', $fixture));
-        }
-        return file_get_contents($file);
+        return $this->getFixture("eit/response/$fixture", 'VuFindSearch');
     }
 
     /**
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EIT/QueryBuilderTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EIT/QueryBuilderTest.php
index 9ef3d5ac234ad0e4f8ad11ca92aac538bbf7ebca..16ba8f55d3e8f2cfd2eaadea79248d1c5dc84156 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EIT/QueryBuilderTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EIT/QueryBuilderTest.php
@@ -42,6 +42,8 @@ use VuFindSearch\Backend\EIT\QueryBuilder;
  */
 class QueryBuilderTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test query parsing.
      *
@@ -61,9 +63,7 @@ class QueryBuilderTest extends TestCase
         foreach ($tests as $test) {
             list($input, $output) = $test;
             $q = unserialize(
-                file_get_contents(
-                    PHPUNIT_SEARCH_FIXTURES . '/eit/query/' . $input
-                )
+                $this->getFixture("eit/query/$input", 'VuFindSearch')
             );
             $response = $qb->build($q);
             $parsedQ = $response->get('query');
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/LibGuides/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/LibGuides/BackendTest.php
index 546ba7b710c390676d8592771fd0ab136cef2e01..2c2b9e1058a471276422234f66d2640ab8ca405c 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/LibGuides/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/LibGuides/BackendTest.php
@@ -28,7 +28,6 @@
  */
 namespace VuFindTest\Backend\LibGuides;
 
-use InvalidArgumentException;
 use Laminas\Http\Client\Adapter\Test as TestAdapter;
 use Laminas\Http\Client as HttpClient;
 use VuFindSearch\Backend\LibGuides\Backend;
@@ -49,6 +48,8 @@ use VuFindSearch\Query\Query;
  */
 class BackendTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test retrieving a record (not supported).
      *
@@ -198,24 +199,6 @@ class BackendTest extends \VuFindTest\Unit\TestCase
 
     /// Internal API
 
-    /**
-     * Load a response as fixture.
-     *
-     * @param string $fixture Fixture file
-     *
-     * @return mixed
-     *
-     * @throws InvalidArgumentException Fixture files does not exist
-     */
-    protected function loadResponse($fixture)
-    {
-        $file = realpath(sprintf('%s/libguides/response/%s', PHPUNIT_SEARCH_FIXTURES, $fixture));
-        if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-            throw new InvalidArgumentException(sprintf('Unable to load fixture file: %s', $fixture));
-        }
-        return file_get_contents($file);
-    }
-
     /**
      * Return connector.
      *
@@ -227,7 +210,9 @@ class BackendTest extends \VuFindTest\Unit\TestCase
     {
         $adapter = new TestAdapter();
         if ($fixture) {
-            $adapter->setResponse($this->loadResponse($fixture));
+            $adapter->setResponse(
+                $this->getFixture("libguides/response/$fixture", 'VuFindSearch')
+            );
         }
         $client = new HttpClient();
         $client->setAdapter($adapter);
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Pazpar2/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Pazpar2/BackendTest.php
index 4df4f5f215ee6b0229e0886c7672eb0f531bcc7e..14f13cd2f74e8e5dabde138bf3ec9abafac10511 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Pazpar2/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Pazpar2/BackendTest.php
@@ -44,6 +44,8 @@ use VuFindTest\Unit\TestCase;
  */
 class BackendTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test that getConnector works.
      *
@@ -133,11 +135,8 @@ class BackendTest extends TestCase
      */
     protected function loadResponse($fixture)
     {
-        $file = realpath(sprintf('%s/pazpar2/response/%s', PHPUNIT_SEARCH_FIXTURES, $fixture));
-        if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-            throw new InvalidArgumentException(sprintf('Unable to load fixture file: %s', $fixture));
-        }
-        return simplexml_load_file($file);
+        $xml = $this->getFixture("pazpar2/response/$fixture", 'VuFindSearch');
+        return simplexml_load_string($xml);
     }
 
     /**
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Primo/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Primo/BackendTest.php
index 8ce5490c53dae1dbfa281a5e9f7d7dd6180bdd29..38e840baf0360914eff0894b00cf261843dbbe28 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Primo/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Primo/BackendTest.php
@@ -44,6 +44,8 @@ use VuFindSearch\Query\Query;
  */
 class BackendTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test retrieving a record.
      *
@@ -193,11 +195,9 @@ class BackendTest extends \VuFindTest\Unit\TestCase
      */
     protected function loadResponse($fixture)
     {
-        $file = realpath(sprintf('%s/primo/response/%s', PHPUNIT_SEARCH_FIXTURES, $fixture));
-        if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-            throw new InvalidArgumentException(sprintf('Unable to load fixture file: %s', $fixture));
-        }
-        return unserialize(file_get_contents($file));
+        return unserialize(
+            $this->getFixture("primo/response/$fixture", 'VuFindSearch')
+        );
     }
 
     /**
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Primo/ConnectorTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Primo/ConnectorTest.php
index 66f48e3762e84f425ed40281e1098bf3fb608e4e..6781311bfe26e793363a0f624e5f85089dacb695 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Primo/ConnectorTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Primo/ConnectorTest.php
@@ -47,6 +47,8 @@ use VuFindSearch\Backend\Primo\Connector;
  */
 class ConnectorTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test default timeout value
      *
@@ -150,11 +152,7 @@ class ConnectorTest extends TestCase
     {
         $adapter = new TestAdapter();
         if ($fixture) {
-            $file = realpath(sprintf('%s/primo/response/%s', PHPUNIT_SEARCH_FIXTURES, $fixture));
-            if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-                throw new InvalidArgumentException(sprintf('Unable to load fixture file: %s', $file));
-            }
-            $response = file_get_contents($file);
+            $response = $this->getFixture("primo/response/$fixture", 'VuFindSearch');
             $adapter->setResponse($response);
         }
         $client = new HttpClient();
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/BackendTest.php
index 2e5960d7558c63dbb3ea287f001736a9e359ee86..1105801807e825098ead5249c1a6fbf09a38fbdc 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/BackendTest.php
@@ -49,6 +49,8 @@ use VuFindSearch\Query\Query;
  */
 class BackendTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test retrieving a record.
      *
@@ -410,11 +412,9 @@ class BackendTest extends TestCase
      */
     protected function loadResponse($fixture)
     {
-        $file = realpath(sprintf('%s/solr/response/%s', PHPUNIT_SEARCH_FIXTURES, $fixture));
-        if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-            throw new InvalidArgumentException(sprintf('Unable to load fixture file: %s', $file));
-        }
-        return Response::fromString(file_get_contents($file));
+        return Response::fromString(
+            $this->getFixture("solr/response/$fixture", 'VuFindSearch')
+        );
     }
 
     /**
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/ConnectorTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/ConnectorTest.php
index 29b34330edd75ef20827b2c87188dd6fe2c22c5d..840469416f4711436986f151585eea98291e01a6 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/ConnectorTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/ConnectorTest.php
@@ -48,6 +48,8 @@ use VuFindSearch\Backend\Solr\HandlerMap;
  */
 class ConnectorTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Current response.
      *
@@ -176,11 +178,8 @@ class ConnectorTest extends TestCase
     protected function createConnector($fixture = null)
     {
         if ($fixture) {
-            $file = realpath(sprintf('%s/solr/response/%s', PHPUNIT_SEARCH_FIXTURES, $fixture));
-            if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-                throw new InvalidArgumentException(sprintf('Unable to load fixture file: %s', $file));
-            }
-            $this->response = file_get_contents($file);
+            $this->response
+                = $this->getFixture("solr/response/$fixture", 'VuFindSearch');
         }
 
         $map  = new HandlerMap(['select' => ['fallback' => true]]);
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Summon/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Summon/BackendTest.php
index 955648acfd40db4bd873bdf813884a127bdbc03b..7c84a97687b1ba4abe72abf45d8c28a62b377e26 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Summon/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Summon/BackendTest.php
@@ -49,6 +49,8 @@ use VuFindSearch\Query\Query;
  */
 class BackendTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Setup method.
      *
@@ -244,11 +246,9 @@ class BackendTest extends TestCase
      */
     protected function loadResponse($fixture)
     {
-        $file = realpath(sprintf('%s/summon/response/%s', PHPUNIT_SEARCH_FIXTURES, $fixture));
-        if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-            throw new InvalidArgumentException(sprintf('Unable to load fixture file: %s', $fixture));
-        }
-        return unserialize(file_get_contents($file));
+        return unserialize(
+            $this->getFixture("summon/response/$fixture", 'VuFindSearch')
+        );
     }
 
     /**
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Summon/QueryBuilderTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Summon/QueryBuilderTest.php
index 189960ab2a7f3cbd7b083c0e5a209221a8ba1436..9c8d33dafffaa52509cb855543c31c03f222d12c 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Summon/QueryBuilderTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Summon/QueryBuilderTest.php
@@ -42,6 +42,8 @@ use VuFindSearch\Backend\Summon\QueryBuilder;
  */
 class QueryBuilderTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test query parsing.
      *
@@ -62,9 +64,7 @@ class QueryBuilderTest extends TestCase
         foreach ($tests as $test) {
             list($input, $output) = $test;
             $q = unserialize(
-                file_get_contents(
-                    PHPUNIT_SEARCH_FIXTURES . '/summon/query/' . $input
-                )
+                $this->getFixture("summon/query/$input", 'VuFindSearch')
             );
             $response = $qb->build($q);
             $processedQ = $response->get('query');
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/BackendTest.php
index 68940f683987105639bd4ad3f92bf1df1ca7dc3c..556d7d59393f5cc320e020213aa31176be3db11f 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/BackendTest.php
@@ -44,6 +44,8 @@ use VuFindSearch\Query\Query;
  */
 class BackendTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test retrieving a record.
      *
@@ -133,11 +135,9 @@ class BackendTest extends TestCase
      */
     protected function loadResponse($fixture)
     {
-        $file = realpath(sprintf('%s/worldcat/response/%s', PHPUNIT_SEARCH_FIXTURES, $fixture));
-        if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
-            throw new InvalidArgumentException(sprintf('Unable to load fixture file: %s', $fixture));
-        }
-        return unserialize(file_get_contents($file));
+        return unserialize(
+            $this->getFixture("worldcat/response/$fixture", 'VuFindSearch')
+        );
     }
 
     /**
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/QueryBuilderTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/QueryBuilderTest.php
index 2358ed3e0b57602bcb8ae7f12b0ce75445cfa3a2..20bb4c34d7ef2e6fe547ae4239d4c40bdb36ce7c 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/QueryBuilderTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/QueryBuilderTest.php
@@ -42,6 +42,8 @@ use VuFindSearch\Backend\WorldCat\QueryBuilder;
  */
 class QueryBuilderTest extends TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Test query parsing.
      *
@@ -62,9 +64,7 @@ class QueryBuilderTest extends TestCase
         foreach ($tests as $test) {
             list($input, $output) = $test;
             $q = unserialize(
-                file_get_contents(
-                    PHPUNIT_SEARCH_FIXTURES . '/worldcat/query/' . $input
-                )
+                $this->getFixture("worldcat/query/$input", 'VuFindSearch')
             );
             $response = $qb->build($q);
             $processedQ = $response->get('query');
@@ -81,7 +81,7 @@ class QueryBuilderTest extends TestCase
     {
         $qb = new QueryBuilder('TEST');
         $q = unserialize(
-            file_get_contents(PHPUNIT_SEARCH_FIXTURES . '/worldcat/query/basic')
+            $this->getFixture('worldcat/query/basic', 'VuFindSearch')
         );
         $response = $qb->build($q);
         $processedQ = $response->get('query');
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/child/child.txt b/module/VuFindTheme/tests/fixtures/themes/child/child.txt
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/child/child.txt
rename to module/VuFindTheme/tests/fixtures/themes/child/child.txt
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/child/css/child.css b/module/VuFindTheme/tests/fixtures/themes/child/css/child.css
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/child/css/child.css
rename to module/VuFindTheme/tests/fixtures/themes/child/css/child.css
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/child/js/extra.js b/module/VuFindTheme/tests/fixtures/themes/child/js/extra.js
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/child/js/extra.js
rename to module/VuFindTheme/tests/fixtures/themes/child/js/extra.js
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/child/js/hello.js b/module/VuFindTheme/tests/fixtures/themes/child/js/hello.js
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/child/js/hello.js
rename to module/VuFindTheme/tests/fixtures/themes/child/js/hello.js
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/child/theme.config.php b/module/VuFindTheme/tests/fixtures/themes/child/theme.config.php
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/child/theme.config.php
rename to module/VuFindTheme/tests/fixtures/themes/child/theme.config.php
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/mixin/js/hello.js b/module/VuFindTheme/tests/fixtures/themes/mixin/js/hello.js
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/mixin/js/hello.js
rename to module/VuFindTheme/tests/fixtures/themes/mixin/js/hello.js
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/mixin/js/mixin.js b/module/VuFindTheme/tests/fixtures/themes/mixin/js/mixin.js
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/mixin/js/mixin.js
rename to module/VuFindTheme/tests/fixtures/themes/mixin/js/mixin.js
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/mixin/mixin.config.php b/module/VuFindTheme/tests/fixtures/themes/mixin/mixin.config.php
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/mixin/mixin.config.php
rename to module/VuFindTheme/tests/fixtures/themes/mixin/mixin.config.php
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/mixin_user/theme.config.php b/module/VuFindTheme/tests/fixtures/themes/mixin_user/theme.config.php
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/mixin_user/theme.config.php
rename to module/VuFindTheme/tests/fixtures/themes/mixin_user/theme.config.php
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/js/hello.js b/module/VuFindTheme/tests/fixtures/themes/parent/js/hello.js
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/js/hello.js
rename to module/VuFindTheme/tests/fixtures/themes/parent/js/hello.js
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/parent.txt b/module/VuFindTheme/tests/fixtures/themes/parent/parent.txt
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/parent.txt
rename to module/VuFindTheme/tests/fixtures/themes/parent/parent.txt
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/everything.phtml b/module/VuFindTheme/tests/fixtures/themes/parent/templates/everything.phtml
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/everything.phtml
rename to module/VuFindTheme/tests/fixtures/themes/parent/templates/everything.phtml
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page1.md b/module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page1.md
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page1.md
rename to module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page1.md
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page1.phtml b/module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page1.phtml
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page1.phtml
rename to module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page1.phtml
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page2_aa.phtml b/module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page2_aa.phtml
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page2_aa.phtml
rename to module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page2_aa.phtml
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page2_bb.phtml b/module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page2_bb.phtml
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page2_bb.phtml
rename to module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page2_bb.phtml
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page3.phtml b/module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page3.phtml
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page3.phtml
rename to module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page3.phtml
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page3_bb.phtml b/module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page3_bb.phtml
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page3_bb.phtml
rename to module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page3_bb.phtml
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page4.md b/module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page4.md
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page4.md
rename to module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page4.md
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page5_aa.md b/module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page5_aa.md
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page5_aa.md
rename to module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page5_aa.md
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page5_bb.md b/module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page5_bb.md
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page5_bb.md
rename to module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page5_bb.md
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page6.md b/module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page6.md
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page6.md
rename to module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page6.md
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page6_bb.md b/module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page6_bb.md
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/templates/page-locator-test/page6_bb.md
rename to module/VuFindTheme/tests/fixtures/themes/parent/templates/page-locator-test/page6_bb.md
diff --git a/module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/theme.config.php b/module/VuFindTheme/tests/fixtures/themes/parent/theme.config.php
similarity index 100%
rename from module/VuFindTheme/tests/unit-tests/fixtures/themes/parent/theme.config.php
rename to module/VuFindTheme/tests/fixtures/themes/parent/theme.config.php
diff --git a/module/VuFindTheme/tests/unit-tests/src/VuFindTest/ThemeCompilerTest.php b/module/VuFindTheme/tests/unit-tests/src/VuFindTest/ThemeCompilerTest.php
index faabc5051c12761cc97864c5badadb5dda18c5e2..b2a9ca755f94eeefbdc9c68c1afeb09e1ee7b211 100644
--- a/module/VuFindTheme/tests/unit-tests/src/VuFindTest/ThemeCompilerTest.php
+++ b/module/VuFindTheme/tests/unit-tests/src/VuFindTest/ThemeCompilerTest.php
@@ -41,12 +41,7 @@ use VuFindTheme\ThemeInfo;
  */
 class ThemeCompilerTest extends Unit\TestCase
 {
-    /**
-     * Path to theme fixtures
-     *
-     * @var string
-     */
-    protected $fixturePath;
+    use \VuFindTest\Unit\FixtureTrait;
 
     /**
      * ThemeInfo object for tests
@@ -69,8 +64,9 @@ class ThemeCompilerTest extends Unit\TestCase
      */
     public function setUp(): void
     {
-        $this->fixturePath = realpath(__DIR__ . '/../../fixtures/themes');
-        $this->info = new ThemeInfo($this->fixturePath, 'parent');
+        $this->info = new ThemeInfo(
+            $this->getFixtureDir('VuFindTheme') . 'themes', 'parent'
+        );
         $this->targetPath = $this->info->getBaseDir() . '/compiled';
         // Give up if the target directory already exists:
         if (is_dir($this->targetPath)) {
diff --git a/module/VuFindTheme/tests/unit-tests/src/VuFindTest/ThemeInfoTest.php b/module/VuFindTheme/tests/unit-tests/src/VuFindTest/ThemeInfoTest.php
index 4548f9da68cd785bfe732c20ccead6209865e0fa..7907563ea81dc8f49df500ed58ae60eefbc1bdf1 100644
--- a/module/VuFindTheme/tests/unit-tests/src/VuFindTest/ThemeInfoTest.php
+++ b/module/VuFindTheme/tests/unit-tests/src/VuFindTest/ThemeInfoTest.php
@@ -40,6 +40,8 @@ use VuFindTheme\ThemeInfo;
  */
 class ThemeInfoTest extends Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Path to theme fixtures
      *
@@ -52,7 +54,8 @@ class ThemeInfoTest extends Unit\TestCase
      */
     public function setUp(): void
     {
-        $this->fixturePath = realpath(__DIR__ . '/../../fixtures/themes');
+        $this->fixturePath
+            = realpath($this->getFixtureDir('VuFindTheme') . 'themes');
     }
 
     /**
diff --git a/module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/ParentTemplateTest.php b/module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/ParentTemplateTest.php
index 585aa6e25dfaebfb9d397bcb5fc6a15f29a6c154..b203afc788b8c8c6d0bd5116cbc829e3ccd8d02e 100644
--- a/module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/ParentTemplateTest.php
+++ b/module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/ParentTemplateTest.php
@@ -40,6 +40,8 @@ use VuFindTheme\View\Helper\ParentTemplate;
  */
 class ParentTemplateTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Path to theme fixtures
      *
@@ -54,7 +56,8 @@ class ParentTemplateTest extends \VuFindTest\Unit\TestCase
      */
     public function setUp(): void
     {
-        $this->fixturePath = realpath(__DIR__ . '/../../../../fixtures/themes');
+        $this->fixturePath
+            = realpath($this->getFixtureDir('VuFindTheme') . 'themes');
     }
 
     /**
diff --git a/module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/TemplatePathTest.php b/module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/TemplatePathTest.php
index 869c97395bb05905d2ec8e34dba083f9a89910cd..a7df6669e48c9237e43e37253ee61bcfa59203f4 100644
--- a/module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/TemplatePathTest.php
+++ b/module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/TemplatePathTest.php
@@ -40,6 +40,8 @@ use VuFindTheme\View\Helper\TemplatePath;
  */
 class TemplatePathTest extends \VuFindTest\Unit\TestCase
 {
+    use \VuFindTest\Unit\FixtureTrait;
+
     /**
      * Path to theme fixtures
      *
@@ -54,7 +56,8 @@ class TemplatePathTest extends \VuFindTest\Unit\TestCase
      */
     public function setUp(): void
     {
-        $this->fixturePath = realpath(__DIR__ . '/../../../../fixtures/themes');
+        $this->fixturePath
+            = realpath($this->getFixtureDir('VuFindTheme') . 'themes');
     }
 
     /**