diff --git a/tests/test_postgrestclient.py b/tests/test_postgrestclient.py
index 265b046d7aae392cb8f550591194556558ea1ca2..33eeed59629bd62d06d3e0f9e24fccfca9ea38b9 100644
--- a/tests/test_postgrestclient.py
+++ b/tests/test_postgrestclient.py
@@ -258,104 +258,15 @@ class TestPgrestClientFilterStrategyNone(TestCase):
 
 
 @Mocker()
-class TestPgrestClientFilterStrategyExact(TestCase):
+class TestPgrestClientFilterCountingStrategies(TestCase):
     def setUp(self):
         super().setUp()
         self.data = SUPERHERO_TEST_DATA
-
-    def test_fetch_all_first(self, mock):
-        # in order to fetch all
-        mock.register_uri(
-            'GET',
-            'http://example.com/superhero',
-            request_headers=DEFAULT_HEADERS,
-            status_code=200,
-            reason='OK',
-            json=self.data
+        self.counting_strategies = (
+            postgrestutils.Count.EXACT,
+            postgrestutils.Count.PLANNED,
+            postgrestutils.Count.ESTIMATED
         )
-        with default_session(count=postgrestutils.Count.EXACT) as s:
-            res = s.filter('superhero')
-
-            self.assertIsInstance(res, postgrestutils.JsonResultSet)  # should return lazy object
-            self.assertFalse(mock.called)  # no request should have been made yet
-
-            self.assertEqual(list(res), self.data)  # fetch data
-            self.assertTrue(mock.called_once)  # should have been called once
-            self.assertEqual(res._result_cache, self.data)  # fetched data should be cached
-            self.assertEqual(res._len_cache, len(self.data))  # len of fetched data should also be cached
-            self.assertEqual(list(res), self.data)  # should utilize cache
-            self.assertEqual(res[:1], self.data[:1])  # should utilize cache
-            self.assertEqual(res[:0], self.data[:0])  # should return empty list
-            self.assertEqual(res[4:2], self.data[4:2])  # should return empty list
-            self.assertEqual(res[2:], self.data[2:])  # should utilize cache
-            self.assertEqual(res[0], self.data[0])  # should utilize cache
-            self.assertTrue(mock.called_once)  # should not have been called again
-
-    def test_fetch_len_first(self, mock):
-        # in order to fetch all
-        mock.register_uri(
-            'GET',
-            'http://example.com/superhero',
-            request_headers=DEFAULT_HEADERS,
-            status_code=200,
-            reason='OK',
-            json=self.data
-        )
-        # in order to fetch first
-        mock.register_uri(
-            'GET',
-            'http://example.com/superhero',
-            request_headers={**DEFAULT_HEADERS, **{'Range-Unit': 'items', 'Range': '0-0'}},
-            status_code=200,
-            reason='OK',
-            headers={'Content-Range': '0-0/*'},
-            json=[self.data[0]]
-        )
-        # in order to fetch range since index 2
-        mock.register_uri(
-            'GET',
-            'http://example.com/superhero',
-            request_headers={**DEFAULT_HEADERS, **{'Range-Unit': 'items', 'Range': '2-'}},
-            status_code=200,
-            reason='OK',
-            headers={'Content-Range': '2-4/*'},
-            json=self.data[2:]
-        )
-        # in order to fetch length
-        mock.register_uri(
-            'GET',
-            'http://example.com/superhero',
-            request_headers={**DEFAULT_HEADERS, **{'Range-Unit': 'items', 'Range': '0-0', 'Prefer': 'count=exact'}},
-            status_code=206,
-            reason='Partial Content',
-            headers={'Content-Range': '0-0/5'},
-            json=self.data[0]
-        )
-        with default_session(count=postgrestutils.Count.EXACT) as s:
-            res = s.filter('superhero')
-
-            self.assertIsInstance(res, postgrestutils.JsonResultSet)  # should return lazy object
-            self.assertFalse(mock.called)  # no request should have been made yet
-
-            self.assertEqual(len(res), len(self.data))  # should fetch len
-            self.assertTrue(mock.called_once)  # should have been called once
-            self.assertEqual(res._len_cache, len(self.data))  # len of fetched data should be cached
-            self.assertEqual(res[:1], self.data[:1])  # should fetch first element as range
-            self.assertEqual(res[:0], self.data[:0])  # should return empty list
-            self.assertEqual(res[4:2], self.data[4:2])  # should return empty list
-            self.assertEqual(res[2:], self.data[2:])  # should fetch range starting at index 2
-            self.assertEqual(res[0], self.data[0])  # should fetch first element as range but return dict
-            self.assertEqual(list(res), self.data)  # should fetch all elements
-            self.assertEqual(res._result_cache, self.data)  # should cache all elements
-            self.assertTrue(mock.called)  # should have been called at least once
-            self.assertEqual(mock.call_count, 5)  # should have been called 5 times (fetch len, range, first and all)
-
-
-@Mocker()
-class TestPgrestClientFilterStrategyPlanned(TestCase):
-    def setUp(self):
-        super().setUp()
-        self.data = SUPERHERO_TEST_DATA
 
     def test_fetch_all_first(self, mock):
         # in order to fetch all
@@ -367,117 +278,26 @@ class TestPgrestClientFilterStrategyPlanned(TestCase):
             reason='OK',
             json=self.data
         )
-        with default_session(count=postgrestutils.Count.PLANNED) as s:
-            res = s.filter('superhero')
-
-            self.assertIsInstance(res, postgrestutils.JsonResultSet)  # should return lazy object
-            self.assertFalse(mock.called)  # no request should have been made yet
-
-            self.assertEqual(list(res), self.data)  # fetch data
-            self.assertTrue(mock.called_once)  # should have been called once
-            self.assertEqual(res._result_cache, self.data)  # fetched data should be cached
-            self.assertEqual(res._len_cache, len(self.data))  # len of fetched data should also be cached
-            self.assertEqual(list(res), self.data)  # should utilize cache
-            self.assertEqual(res[:1], self.data[:1])  # should utilize cache
-            self.assertEqual(res[:0], self.data[:0])  # should return empty list
-            self.assertEqual(res[4:2], self.data[4:2])  # should return empty list
-            self.assertEqual(res[2:], self.data[2:])  # should utilize cache
-            self.assertEqual(res[0], self.data[0])  # should utilize cache
-            self.assertTrue(mock.called_once)  # should not have been called again
-
-    def test_fetch_len_first(self, mock):
-        # in order to fetch all
-        mock.register_uri(
-            'GET',
-            'http://example.com/superhero',
-            request_headers=DEFAULT_HEADERS,
-            status_code=200,
-            reason='OK',
-            json=self.data
-        )
-        # in order to fetch first
-        mock.register_uri(
-            'GET',
-            'http://example.com/superhero',
-            request_headers={**DEFAULT_HEADERS, **{'Range-Unit': 'items', 'Range': '0-0'}},
-            status_code=200,
-            reason='OK',
-            headers={'Content-Range': '0-0/*'},
-            json=[self.data[0]]
-        )
-        # in order to fetch range since index 2
-        mock.register_uri(
-            'GET',
-            'http://example.com/superhero',
-            request_headers={**DEFAULT_HEADERS, **{'Range-Unit': 'items', 'Range': '2-'}},
-            status_code=200,
-            reason='OK',
-            headers={'Content-Range': '2-4/*'},
-            json=self.data[2:]
-        )
-        # in order to fetch length
-        mock.register_uri(
-            'GET',
-            'http://example.com/superhero',
-            request_headers={**DEFAULT_HEADERS, **{'Range-Unit': 'items', 'Range': '0-0', 'Prefer': 'count=planned'}},
-            status_code=206,
-            reason='Partial Content',
-            headers={'Content-Range': '0-0/5'},
-            json=self.data[0]
-        )
-        with default_session(count=postgrestutils.Count.PLANNED) as s:
-            res = s.filter('superhero')
-
-            self.assertIsInstance(res, postgrestutils.JsonResultSet)  # should return lazy object
-            self.assertFalse(mock.called)  # no request should have been made yet
-
-            self.assertEqual(len(res), len(self.data))  # should fetch len
-            self.assertTrue(mock.called_once)  # should have been called once
-            self.assertEqual(res._len_cache, len(self.data))  # len of fetched data should be cached
-            self.assertEqual(res[:1], self.data[:1])  # should fetch first element as range
-            self.assertEqual(res[:0], self.data[:0])  # should return empty list
-            self.assertEqual(res[4:2], self.data[4:2])  # should return empty list
-            self.assertEqual(res[2:], self.data[2:])  # should fetch range starting at index 2
-            self.assertEqual(res[0], self.data[0])  # should fetch first element as range but return dict
-            self.assertEqual(list(res), self.data)  # should fetch all elements
-            self.assertEqual(res._result_cache, self.data)  # should cache all elements
-            self.assertTrue(mock.called)  # should have been called at least once
-            self.assertEqual(mock.call_count, 5)  # should have been called 5 times (fetch len, range, first and all)
+        for strategy in self.counting_strategies:
+            mock.reset()
+            with default_session(count=strategy) as s:
+                res = s.filter('superhero')
 
+                self.assertIsInstance(res, postgrestutils.JsonResultSet)  # should return lazy object
+                self.assertFalse(mock.called)  # no request should have been made yet
 
-@Mocker()
-class TestPgrestClientFilterStrategyEstimated(TestCase):
-    def setUp(self):
-        super().setUp()
-        self.data = SUPERHERO_TEST_DATA
+                self.assertEqual(list(res), self.data)  # fetch data
+                self.assertTrue(mock.called_once)  # should have been called once
+                self.assertEqual(res._result_cache, self.data)  # fetched data should be cached
+                self.assertEqual(res._len_cache, len(self.data))  # len of fetched data should be cached
 
-    def test_fetch_all_first(self, mock):
-        # in order to fetch all
-        mock.register_uri(
-            'GET',
-            'http://example.com/superhero',
-            request_headers=DEFAULT_HEADERS,
-            status_code=200,
-            reason='OK',
-            json=self.data
-        )
-        with default_session(count=postgrestutils.Count.ESTIMATED) as s:
-            res = s.filter('superhero')
-
-            self.assertIsInstance(res, postgrestutils.JsonResultSet)  # should return lazy object
-            self.assertFalse(mock.called)  # no request should have been made yet
-
-            self.assertEqual(list(res), self.data)  # fetch data
-            self.assertTrue(mock.called_once)  # should have been called once
-            self.assertEqual(res._result_cache, self.data)  # fetched data should be cached
-            self.assertEqual(res._len_cache, len(self.data))  # len of fetched data should also be cached
-            self.assertEqual(list(res), self.data)  # should utilize cache
-            self.assertEqual(res[:1], self.data[:1])  # should utilize cache
-            self.assertEqual(res[:0], self.data[:0])  # should return empty list
-            self.assertEqual(res[4:2], self.data[4:2])  # should return empty list
-            self.assertEqual(res[2:], self.data[2:])  # should utilize cache
-            self.assertEqual(res[0], self.data[0])  # should utilize cache
-            self.assertTrue(mock.called_once)  # should not have been called again
+                self.assertEqual(list(res), self.data)  # should utilize cache
+                self.assertEqual(res[:1], self.data[:1])  # should utilize cache
+                self.assertEqual(res[:0], self.data[:0])  # should return empty list
+                self.assertEqual(res[4:2], self.data[4:2])  # should return empty list
+                self.assertEqual(res[2:], self.data[2:])  # should utilize cache
+                self.assertEqual(res[0], self.data[0])  # should utilize cache
+                self.assertTrue(mock.called_once)  # should not have been called again
 
     def test_fetch_len_first(self, mock):
         # in order to fetch all
@@ -509,37 +329,44 @@ class TestPgrestClientFilterStrategyEstimated(TestCase):
             headers={'Content-Range': '2-4/*'},
             json=self.data[2:]
         )
-        # in order to fetch length
-        mock.register_uri(
-            'GET',
-            'http://example.com/superhero',
-            request_headers={
-                **DEFAULT_HEADERS,
-                **{'Range-Unit': 'items', 'Range': '0-0', 'Prefer': 'count=estimated'}
-            },
-            status_code=206,
-            reason='Partial Content',
-            headers={'Content-Range': '0-0/5'},
-            json=self.data[0]
-        )
-        with default_session(count=postgrestutils.Count.ESTIMATED) as s:
-            res = s.filter('superhero')
-
-            self.assertIsInstance(res, postgrestutils.JsonResultSet)  # should return lazy object
-            self.assertFalse(mock.called)  # no request should have been made yet
+        # in order to fetch length using different strategies
+        for strategy in self.counting_strategies:
+            mock.register_uri(
+                'GET',
+                'http://example.com/superhero',
+                request_headers={
+                    **DEFAULT_HEADERS,
+                    **{'Range-Unit': 'items', 'Range': '0-0', 'Prefer': 'count={}'.format(strategy.value)}
+                },
+                status_code=206,
+                reason='Partial Content',
+                headers={'Content-Range': '0-0/5'},
+                json=self.data[0]
+            )
+            mock.reset()
 
-            self.assertEqual(len(res), len(self.data))  # should fetch len
-            self.assertTrue(mock.called_once)  # should have been called once
-            self.assertEqual(res._len_cache, len(self.data))  # len of fetched data should be cached
-            self.assertEqual(res[:1], self.data[:1])  # should fetch first element as range
-            self.assertEqual(res[:0], self.data[:0])  # should return empty list
-            self.assertEqual(res[4:2], self.data[4:2])  # should return empty list
-            self.assertEqual(res[2:], self.data[2:])  # should fetch range starting at index 2
-            self.assertEqual(res[0], self.data[0])  # should fetch first element as range but return dict
-            self.assertEqual(list(res), self.data)  # should fetch all elements
-            self.assertEqual(res._result_cache, self.data)  # should cache all elements
-            self.assertTrue(mock.called)  # should have been called at least once
-            self.assertEqual(mock.call_count, 5)  # should have been called 5 times (fetch len, range, first and all)
+            with default_session(count=strategy) as s:
+                res = s.filter('superhero')
+
+                self.assertIsInstance(res, postgrestutils.JsonResultSet)  # should return lazy object
+                self.assertFalse(mock.called)  # no request should have been made yet
+
+                self.assertEqual(len(res), len(self.data))  # should fetch len
+                self.assertTrue(mock.called_once)  # should have been called once
+                self.assertEqual(res._len_cache, len(self.data))  # len of fetched data should be cached
+
+                self.assertEqual(res[:1], self.data[:1])  # should fetch first element as range
+                self.assertEqual(res[:0], self.data[:0])  # should return empty list
+                self.assertEqual(res[4:2], self.data[4:2])  # should return empty list
+                self.assertEqual(res[2:], self.data[2:])  # should fetch range starting at index 2
+                self.assertEqual(res[0], self.data[0])  # should fetch first element as range but return dict
+                self.assertEqual(list(res), self.data)  # should fetch all elements
+                self.assertEqual(res._result_cache, self.data)  # should fetch all elements
+                self.assertEqual(res._result_cache, self.data)  # should cache all elements
+                self.assertTrue(mock.called)  # should have been called at least once
+                # should have been called 5 times (fetch len, fetch 2 ranges,
+                # fetch first and fetch all)
+                self.assertEqual(mock.call_count, 5)
 
 
 @Mocker()