Repository: plone/plone.restapi (language: python)

Issue:
block transformer tests register adapters which should be cleaned up in the tests
```
    def test_disabled_deserializer(self):
        @implementer(IBlockFieldDeserializationTransformer)
        @adapter(IBlocks, IBrowserRequest)
        class TestAdapter(object):
            order = 10
            block_type = "test"
            disabled = True

            def __init__(self, context, request):
                self.context = context
                self.request = request

            def __call__(self, value):
                self.context._handler_called = True

                value["value"] = u"changed: {}".format(value["value"])

                return value

        provideSubscriptionAdapter(
            TestAdapter,
            (IDexterityItem, IBrowserRequest),
        )

        self.deserialize(blocks={"123": {"@type": "test", "value": u"text"}})

        assert not getattr(self.portal.doc1, "_handler_called", False)
        assert self.portal.doc1.blocks["123"]["value"] == u"text"
```

This adapter live after the execution of the test, so the tests don't run in isolation. The adapter should be unregistered.


Discussion / hints:
I often see plone.restapi failures on Jenkins. More often on 5.2 Py 2.7. And more often on PR jobs. Rerunning the job helps.
I wonder if this is a cause of some of those, so would be great if someone can have a look.

Fix patch:
diff --git a/news/1083.bugfix b/news/1083.bugfix
new file mode 100644
index 0000000000..0628e8cdb1
--- /dev/null
+++ b/news/1083.bugfix
@@ -0,0 +1,1 @@
+Add GSM unsubscribe for test registered adapters in block transformer tests @tiberiuichim


Test patch:
diff --git a/src/plone/restapi/tests/test_blocks_deserializer.py b/src/plone/restapi/tests/test_blocks_deserializer.py
index b0ac5499fc..9aae50e08d 100644
--- a/src/plone/restapi/tests/test_blocks_deserializer.py
+++ b/src/plone/restapi/tests/test_blocks_deserializer.py
@@ -8,6 +8,7 @@
 from plone.restapi.testing import PLONE_RESTAPI_DX_INTEGRATION_TESTING
 from plone.uuid.interfaces import IUUID
 from zope.component import adapter
+from zope.component import getGlobalSiteManager
 from zope.component import getMultiAdapter
 from zope.component import provideSubscriptionAdapter
 from zope.component import queryUtility
@@ -76,6 +77,13 @@ def __call__(self, value):
         assert self.portal.doc1._handler_called is True
         assert self.portal.doc1.blocks["123"]["value"] == u"changed: text"
 
+        sm = getGlobalSiteManager()
+        sm.adapters.unsubscribe(
+            (IDexterityItem, IBrowserRequest),
+            IBlockFieldDeserializationTransformer,
+            TestAdapter,
+        )
+
     def test_disabled_deserializer(self):
         @implementer(IBlockFieldDeserializationTransformer)
         @adapter(IBlocks, IBrowserRequest)
@@ -105,6 +113,13 @@ def __call__(self, value):
         assert not getattr(self.portal.doc1, "_handler_called", False)
         assert self.portal.doc1.blocks["123"]["value"] == u"text"
 
+        sm = getGlobalSiteManager()
+        sm.adapters.unsubscribe(
+            (IDexterityItem, IBrowserRequest),
+            IBlockFieldDeserializationTransformer,
+            TestAdapter,
+        )
+
     def test_register_multiple_transform(self):
         @implementer(IBlockFieldDeserializationTransformer)
         @adapter(IBlocks, IBrowserRequest)
@@ -156,6 +171,18 @@ def __call__(self, value):
         self.assertTrue(self.portal.doc1._handler_called_b)
         self.assertEqual(self.portal.doc1.blocks["123"]["value"], u"c")
 
+        sm = getGlobalSiteManager()
+        sm.adapters.unsubscribe(
+            (IDexterityItem, IBrowserRequest),
+            IBlockFieldDeserializationTransformer,
+            TestAdapterA,
+        )
+        sm.adapters.unsubscribe(
+            (IDexterityItem, IBrowserRequest),
+            IBlockFieldDeserializationTransformer,
+            TestAdapterB,
+        )
+
     def test_blocks_html_cleanup(self):
         self.deserialize(
             blocks={
diff --git a/src/plone/restapi/tests/test_blocks_serializer.py b/src/plone/restapi/tests/test_blocks_serializer.py
index 9eb4ffa81b..38222b98af 100644
--- a/src/plone/restapi/tests/test_blocks_serializer.py
+++ b/src/plone/restapi/tests/test_blocks_serializer.py
@@ -10,6 +10,7 @@
 from plone.uuid.interfaces import IUUID
 from z3c.form.interfaces import IDataManager
 from zope.component import adapter
+from zope.component import getGlobalSiteManager
 from zope.component import getMultiAdapter
 from zope.component import provideSubscriptionAdapter
 from zope.component import queryUtility
@@ -92,6 +93,18 @@ def __call__(self, value):
         )
         self.assertEqual(value["123"]["value"], u"c")
 
+        sm = getGlobalSiteManager()
+        sm.adapters.unsubscribe(
+            (IDexterityItem, IBrowserRequest),
+            IBlockFieldSerializationTransformer,
+            TestAdapterA,
+        )
+        sm.adapters.unsubscribe(
+            (IDexterityItem, IBrowserRequest),
+            IBlockFieldSerializationTransformer,
+            TestAdapterB,
+        )
+
     def test_disabled_serializer(self):
         @implementer(IBlockFieldSerializationTransformer)
         @adapter(IBlocks, IBrowserRequest)
@@ -123,6 +136,13 @@ def __call__(self, value):
         assert not getattr(self.portal.doc1, "_handler_called", False)
         self.assertEqual(value["123"]["value"], u"text")
 
+        sm = getGlobalSiteManager()
+        sm.adapters.unsubscribe(
+            (IDexterityItem, IBrowserRequest),
+            IBlockFieldSerializationTransformer,
+            TestAdapter,
+        )
+
     def test_serialize_blocks_smart_href_array_volto_object_browser(self):
         doc_uid = IUUID(self.portal.doc1)
         value = self.serialize(