Converted unit tests in src/controller/tests/data_model from NL to PW. (#33371)

* Converted src/controller/tests/data_model from NL to PW.

* Updated to accomodate the fact that AppContext and LoopbackMessagingContext now have SetUp/SetUpTestSuite returning void.

* Comment cleanup.

* Reordered tests to fix dependency.

* Formatting

* Formatting

* Added comment warning of order dependence.

* Formatting

* Removed unneeded conditions from SetUpTestSuite/TearDownTestSuite.
diff --git a/src/controller/tests/data_model/BUILD.gn b/src/controller/tests/data_model/BUILD.gn
index e7621af..017980c 100644
--- a/src/controller/tests/data_model/BUILD.gn
+++ b/src/controller/tests/data_model/BUILD.gn
@@ -14,12 +14,12 @@
 
 import("//build_overrides/build.gni")
 import("//build_overrides/chip.gni")
-import("//build_overrides/nlunit_test.gni")
+import("//build_overrides/pigweed.gni")
 
 import("${chip_root}/build/chip/chip_test_suite.gni")
 import("${chip_root}/src/platform/device.gni")
 
-chip_test_suite_using_nltest("data_model") {
+chip_test_suite("data_model") {
   output_name = "libDataModelTests"
 
   if (chip_device_platform != "mbed" && chip_device_platform != "efr32" &&
@@ -35,9 +35,7 @@
     "${chip_root}/src/app/tests:helpers",
     "${chip_root}/src/app/util/mock:mock_ember",
     "${chip_root}/src/controller",
-    "${chip_root}/src/lib/support:testing_nlunit",
     "${chip_root}/src/messaging/tests:helpers",
     "${chip_root}/src/transport/raw/tests:helpers",
-    "${nlunit_test_root}:nlunit-test",
   ]
 }
diff --git a/src/controller/tests/data_model/TestCommands.cpp b/src/controller/tests/data_model/TestCommands.cpp
index 7c585bf..adc6bd0 100644
--- a/src/controller/tests/data_model/TestCommands.cpp
+++ b/src/controller/tests/data_model/TestCommands.cpp
@@ -22,6 +22,8 @@
  *
  */
 
+#include <gtest/gtest.h>
+
 #include "app/data-model/NullObject.h"
 #include <app-common/zap-generated/cluster-objects.h>
 #include <app/AppConfig.h>
@@ -32,11 +34,8 @@
 #include <lib/core/ErrorStr.h>
 #include <lib/core/TLV.h>
 #include <lib/core/TLVUtilities.h>
-#include <lib/support/UnitTestContext.h>
-#include <lib/support/UnitTestRegistration.h>
 #include <lib/support/logging/CHIPLogging.h>
 #include <messaging/tests/MessagingContext.h>
-#include <nlunit-test.h>
 #include <protocols/interaction_model/Constants.h>
 
 using TestContext = chip::Test::AppContext;
@@ -180,25 +179,37 @@
 
 namespace {
 
-class TestCommandInteraction
+class TestCommands : public ::testing::Test
 {
 public:
-    TestCommandInteraction() {}
-    static void TestDataResponse(nlTestSuite * apSuite, void * apContext);
-    static void TestSuccessNoDataResponse(nlTestSuite * apSuite, void * apContext);
-    static void TestMultipleSuccessNoDataResponses(nlTestSuite * apSuite, void * apContext);
-    static void TestAsyncResponse(nlTestSuite * apSuite, void * apContext);
-    static void TestFailure(nlTestSuite * apSuite, void * apContext);
-    static void TestMultipleFailures(nlTestSuite * apSuite, void * apContext);
-    static void TestSuccessNoDataResponseWithClusterStatus(nlTestSuite * apSuite, void * apContext);
-    static void TestFailureWithClusterStatus(nlTestSuite * apSuite, void * apContext);
+    // Performs shared setup for all tests in the test suite
+    static void SetUpTestSuite()
+    {
+        mpContext = new TestContext();
+        ASSERT_NE(mpContext, nullptr);
+        mpContext->SetUpTestSuite();
+    }
 
-private:
+    // Performs shared teardown for all tests in the test suite
+    static void TearDownTestSuite()
+    {
+        mpContext->TearDownTestSuite();
+        delete mpContext;
+    }
+
+protected:
+    // Performs setup for each individual test in the test suite
+    void SetUp() { mpContext->SetUp(); }
+
+    // Performs teardown for each individual test in the test suite
+    void TearDown() { mpContext->TearDown(); }
+
+    static TestContext * mpContext;
 };
+TestContext * TestCommands::mpContext = nullptr;
 
-void TestCommandInteraction::TestDataResponse(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestCommands, TestDataResponse)
 {
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
     // We want to send a TestSimpleArgumentRequest::Type, but get a
     // TestStructArrayArgumentResponse in return, so need to shadow the actual
     // ResponseType that TestSimpleArgumentRequest has.
@@ -208,7 +219,7 @@
     };
 
     FakeRequest request;
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
     bool onSuccessWasCalled = false;
     bool onFailureWasCalled = false;
@@ -217,23 +228,23 @@
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onSuccessCb = [apSuite, &onSuccessWasCalled](const app::ConcreteCommandPath & commandPath, const app::StatusIB & aStatus,
-                                                      const auto & dataResponse) {
+    auto onSuccessCb = [&onSuccessWasCalled](const app::ConcreteCommandPath & commandPath, const app::StatusIB & aStatus,
+                                             const auto & dataResponse) {
         uint8_t i = 0;
         auto iter = dataResponse.arg1.begin();
         while (iter.Next())
         {
             auto & item = iter.GetValue();
 
-            NL_TEST_ASSERT(apSuite, item.a == i);
-            NL_TEST_ASSERT(apSuite, item.b == false);
-            NL_TEST_ASSERT(apSuite, item.c.a == i);
-            NL_TEST_ASSERT(apSuite, item.c.b == true);
+            EXPECT_EQ(item.a, i);
+            EXPECT_FALSE(item.b);
+            EXPECT_EQ(item.c.a, i);
+            EXPECT_TRUE(item.c.b);
             i++;
         }
 
-        NL_TEST_ASSERT(apSuite, iter.GetStatus() == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, dataResponse.arg6 == true);
+        EXPECT_EQ(iter.GetStatus(), CHIP_NO_ERROR);
+        EXPECT_TRUE(dataResponse.arg6);
 
         onSuccessWasCalled = true;
     };
@@ -244,25 +255,24 @@
 
     responseDirective = kSendDataResponse;
 
-    chip::Controller::InvokeCommandRequest(&ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb,
+    chip::Controller::InvokeCommandRequest(&mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb,
                                            onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, onSuccessWasCalled && !onFailureWasCalled);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(onSuccessWasCalled && !onFailureWasCalled);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestCommandInteraction::TestSuccessNoDataResponse(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestCommands, TestSuccessNoDataResponse)
 {
     struct FakeRequest : public Clusters::UnitTesting::Commands::TestSimpleArgumentRequest::Type
     {
         using ResponseType = DataModel::NullObjectType;
     };
 
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
     FakeRequest request;
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
     bool onSuccessWasCalled = false;
     bool onFailureWasCalled = false;
@@ -283,25 +293,24 @@
 
     responseDirective = kSendSuccessStatusCode;
 
-    chip::Controller::InvokeCommandRequest(&ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb,
+    chip::Controller::InvokeCommandRequest(&mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb,
                                            onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, onSuccessWasCalled && !onFailureWasCalled && statusCheck);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(onSuccessWasCalled && !onFailureWasCalled && statusCheck);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestCommandInteraction::TestMultipleSuccessNoDataResponses(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestCommands, TestMultipleSuccessNoDataResponses)
 {
     struct FakeRequest : public Clusters::UnitTesting::Commands::TestSimpleArgumentRequest::Type
     {
         using ResponseType = DataModel::NullObjectType;
     };
 
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
     FakeRequest request;
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
     size_t successCalls = 0;
     size_t failureCalls = 0;
@@ -322,25 +331,25 @@
 
     responseDirective = kSendMultipleSuccessStatusCodes;
 
-    Controller::InvokeCommandRequest(&ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb, onFailureCb);
+    Controller::InvokeCommandRequest(&mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb,
+                                     onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, successCalls == 1 && statusCheck);
-    NL_TEST_ASSERT(apSuite, failureCalls == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(successCalls == 1 && statusCheck);
+    EXPECT_EQ(failureCalls, 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestCommandInteraction::TestAsyncResponse(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestCommands, TestAsyncResponse)
 {
     struct FakeRequest : public Clusters::UnitTesting::Commands::TestSimpleArgumentRequest::Type
     {
         using ResponseType = DataModel::NullObjectType;
     };
 
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
     FakeRequest request;
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
     bool onSuccessWasCalled = false;
     bool onFailureWasCalled = false;
@@ -361,37 +370,31 @@
 
     responseDirective = kAsync;
 
-    chip::Controller::InvokeCommandRequest(&ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb,
+    chip::Controller::InvokeCommandRequest(&mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb,
                                            onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, !onSuccessWasCalled && !onFailureWasCalled && !statusCheck);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 2);
+    EXPECT_TRUE(!onSuccessWasCalled && !onFailureWasCalled && !statusCheck);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 2u);
 
     CommandHandler * commandHandle = asyncHandle.Get();
-    NL_TEST_ASSERT(apSuite, commandHandle != nullptr);
-
-    if (commandHandle == nullptr)
-    {
-        return;
-    }
+    ASSERT_NE(commandHandle, nullptr);
 
     commandHandle->AddStatus(ConcreteCommandPath(kTestEndpointId, request.GetClusterId(), request.GetCommandId()),
                              Protocols::InteractionModel::Status::Success);
     asyncHandle.Release();
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, onSuccessWasCalled && !onFailureWasCalled && statusCheck);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(onSuccessWasCalled && !onFailureWasCalled && statusCheck);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestCommandInteraction::TestFailure(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestCommands, TestFailure)
 {
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
     Clusters::UnitTesting::Commands::TestSimpleArgumentRequest::Type request;
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
     bool onSuccessWasCalled = false;
     bool onFailureWasCalled = false;
@@ -412,25 +415,24 @@
 
     responseDirective = kSendError;
 
-    chip::Controller::InvokeCommandRequest(&ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb,
+    chip::Controller::InvokeCommandRequest(&mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb,
                                            onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, !onSuccessWasCalled && onFailureWasCalled && statusCheck);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(!onSuccessWasCalled && onFailureWasCalled && statusCheck);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestCommandInteraction::TestMultipleFailures(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestCommands, TestMultipleFailures)
 {
     struct FakeRequest : public Clusters::UnitTesting::Commands::TestSimpleArgumentRequest::Type
     {
         using ResponseType = DataModel::NullObjectType;
     };
 
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
     FakeRequest request;
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
     size_t successCalls = 0;
     size_t failureCalls = 0;
@@ -451,25 +453,25 @@
 
     responseDirective = kSendMultipleErrors;
 
-    Controller::InvokeCommandRequest(&ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb, onFailureCb);
+    Controller::InvokeCommandRequest(&mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb,
+                                     onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, successCalls == 0);
-    NL_TEST_ASSERT(apSuite, failureCalls == 1 && statusCheck);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(successCalls, 0u);
+    EXPECT_TRUE(failureCalls == 1 && statusCheck);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestCommandInteraction::TestSuccessNoDataResponseWithClusterStatus(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestCommands, TestSuccessNoDataResponseWithClusterStatus)
 {
     struct FakeRequest : public Clusters::UnitTesting::Commands::TestSimpleArgumentRequest::Type
     {
         using ResponseType = DataModel::NullObjectType;
     };
 
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
     FakeRequest request;
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
     bool onSuccessWasCalled = false;
     bool onFailureWasCalled = false;
@@ -491,20 +493,19 @@
 
     responseDirective = kSendSuccessStatusCodeWithClusterStatus;
 
-    chip::Controller::InvokeCommandRequest(&ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb,
+    chip::Controller::InvokeCommandRequest(&mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb,
                                            onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, onSuccessWasCalled && !onFailureWasCalled && statusCheck);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(onSuccessWasCalled && !onFailureWasCalled && statusCheck);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestCommandInteraction::TestFailureWithClusterStatus(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestCommands, TestFailureWithClusterStatus)
 {
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
     Clusters::UnitTesting::Commands::TestSimpleArgumentRequest::Type request;
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
     bool onSuccessWasCalled = false;
     bool onFailureWasCalled = false;
@@ -531,41 +532,13 @@
 
     responseDirective = kSendErrorWithClusterStatus;
 
-    chip::Controller::InvokeCommandRequest(&ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb,
+    chip::Controller::InvokeCommandRequest(&mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, request, onSuccessCb,
                                            onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, !onSuccessWasCalled && onFailureWasCalled && statusCheck);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(!onSuccessWasCalled && onFailureWasCalled && statusCheck);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-const nlTest sTests[] = {
-    NL_TEST_DEF("TestDataResponse", TestCommandInteraction::TestDataResponse),
-    NL_TEST_DEF("TestSuccessNoDataResponse", TestCommandInteraction::TestSuccessNoDataResponse),
-    NL_TEST_DEF("TestMultipleSuccessNoDataResponses", TestCommandInteraction::TestMultipleSuccessNoDataResponses),
-    NL_TEST_DEF("TestAsyncResponse", TestCommandInteraction::TestAsyncResponse),
-    NL_TEST_DEF("TestFailure", TestCommandInteraction::TestFailure),
-    NL_TEST_DEF("TestMultipleFailures", TestCommandInteraction::TestMultipleFailures),
-    NL_TEST_DEF("TestSuccessNoDataResponseWithClusterStatus", TestCommandInteraction::TestSuccessNoDataResponseWithClusterStatus),
-    NL_TEST_DEF("TestFailureWithClusterStatus", TestCommandInteraction::TestFailureWithClusterStatus),
-    NL_TEST_SENTINEL(),
-};
-
-nlTestSuite sSuite = {
-    "TestCommands",
-    &sTests[0],
-    TestContext::nlTestSetUpTestSuite,
-    TestContext::nlTestTearDownTestSuite,
-    TestContext::nlTestSetUp,
-    TestContext::nlTestTearDown,
-};
-
 } // namespace
-
-int TestCommandInteractionTest()
-{
-    return chip::ExecuteTestsWithContext<TestContext>(&sSuite);
-}
-
-CHIP_REGISTER_TEST_SUITE(TestCommandInteractionTest)
diff --git a/src/controller/tests/data_model/TestRead.cpp b/src/controller/tests/data_model/TestRead.cpp
index bcf0233..a27eb61 100644
--- a/src/controller/tests/data_model/TestRead.cpp
+++ b/src/controller/tests/data_model/TestRead.cpp
@@ -16,6 +16,8 @@
  *    limitations under the License.
  */
 
+#include <gtest/gtest.h>
+
 #include "system/SystemClock.h"
 #include "transport/SecureSession.h"
 #include <app-common/zap-generated/cluster-objects.h>
@@ -28,11 +30,8 @@
 #include <app/util/mock/Functions.h>
 #include <controller/ReadInteraction.h>
 #include <lib/core/ErrorStr.h>
-#include <lib/support/UnitTestContext.h>
-#include <lib/support/UnitTestRegistration.h>
 #include <lib/support/logging/CHIPLogging.h>
 #include <messaging/tests/MessagingContext.h>
-#include <nlunit-test.h>
 #include <protocols/interaction_model/Constants.h>
 
 using TestContext = chip::Test::AppContext;
@@ -259,56 +258,40 @@
 
 namespace {
 
-class TestReadInteraction : public app::ReadHandler::ApplicationCallback
+class TestRead : public ::testing::Test, public app::ReadHandler::ApplicationCallback
 {
 public:
-    TestReadInteraction() {}
+    // Performs shared setup for all tests in the test suite
+    static void SetUpTestSuite()
+    {
+        if (mpContext == nullptr)
+        {
+            mpContext = new TestContext();
+            ASSERT_NE(mpContext, nullptr);
+        }
+        mpContext->SetUpTestSuite();
+    }
 
-    static void TestReadAttributeResponse(nlTestSuite * apSuite, void * apContext);
-    static void TestReadAttributeError(nlTestSuite * apSuite, void * apContext);
-    static void TestReadAttributeTimeout(nlTestSuite * apSuite, void * apContext);
-    static void TestSubscribeAttributeTimeout(nlTestSuite * apSuite, void * apContext);
-    static void TestResubscribeAttributeTimeout(nlTestSuite * apSuite, void * apContext);
-    static void TestReadEventResponse(nlTestSuite * apSuite, void * apContext);
-    static void TestReadFabricScopedWithoutFabricFilter(nlTestSuite * apSuite, void * apContext);
-    static void TestReadFabricScopedWithFabricFilter(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_MultipleSubscriptions(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_SubscriptionAppRejection(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_MultipleReads(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_OneSubscribeMultipleReads(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_TwoSubscribesMultipleReads(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_MultipleSubscriptionsWithDataVersionFilter(nlTestSuite * apSuite, void * apContext);
-#if CHIP_CONFIG_ENABLE_ICD_SERVER != 1
-    static void TestReadHandler_SubscriptionReportingIntervalsTest1(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_SubscriptionReportingIntervalsTest2(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_SubscriptionReportingIntervalsTest3(nlTestSuite * apSuite, void * apContext);
-#endif // CHIP_CONFIG_ENABLE_ICD_SERVER
-    static void TestReadHandler_SubscriptionReportingIntervalsTest4(nlTestSuite * apSuite, void * apContext);
-#if CHIP_CONFIG_ENABLE_ICD_SERVER != 1
-    static void TestReadHandler_SubscriptionReportingIntervalsTest5(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_SubscriptionReportingIntervalsTest6(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_SubscriptionReportingIntervalsTest7(nlTestSuite * apSuite, void * apContext);
-#endif // CHIP_CONFIG_ENABLE_ICD_SERVER
-    static void TestReadHandler_SubscriptionReportingIntervalsTest8(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_SubscriptionReportingIntervalsTest9(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandlerResourceExhaustion_MultipleReads(nlTestSuite * apSuite, void * apContext);
-    static void TestReadSubscribeAttributeResponseWithCache(nlTestSuite * apSuite, void * apContext);
-    static void TestReadSubscribeAttributeResponseWithVersionOnlyCache(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_KillOverQuotaSubscriptions(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_KillOldestSubscriptions(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_ParallelReads(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_TooManyPaths(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_TwoParallelReadsSecondTooManyPaths(nlTestSuite * apSuite, void * apContext);
-    static void TestReadAttribute_ManyDataValues(nlTestSuite * apSuite, void * apContext);
-    static void TestReadAttribute_ManyDataValuesWrongPath(nlTestSuite * apSuite, void * apContext);
-    static void TestReadAttribute_ManyErrors(nlTestSuite * apSuite, void * apContext);
-    static void TestSubscribeAttributeDeniedNotExistPath(nlTestSuite * apSuite, void * apContext);
-    static void TestReadHandler_KeepSubscriptionTest(nlTestSuite * apSuite, void * apContext);
-    static void TestSubscribe_OnActiveModeNotification(nlTestSuite * apSuite, void * apContext);
-    static void TestSubscribe_ImmediatelyResubscriptionForLIT(nlTestSuite * apSuite, void * apContext);
-    static void TestSubscribe_DynamicLITSubscription(nlTestSuite * apSuite, void * apContext);
+    // Performs shared teardown for all tests in the test suite
+    static void TearDownTestSuite()
+    {
+        mpContext->TearDownTestSuite();
+        if (mpContext != nullptr)
+        {
+            delete mpContext;
+            mpContext = nullptr;
+        }
+    }
 
-private:
+protected:
+    // Performs setup for each individual test in the test suite
+    void SetUp() { mpContext->SetUp(); }
+
+    // Performs teardown for each individual test in the test suite
+    void TearDown() { mpContext->TearDown(); }
+
+    static TestContext * mpContext;
+
     static uint16_t mMaxInterval;
 
     CHIP_ERROR OnSubscriptionRequested(app::ReadHandler & aReadHandler, Transport::SecureSession & aSecureSession)
@@ -328,16 +311,16 @@
 
     // Issue the given number of reads in parallel and wait for them all to
     // succeed.
-    static void MultipleReadHelper(nlTestSuite * apSuite, TestContext & aCtx, size_t aReadCount);
+    static void MultipleReadHelper(TestContext * apCtx, size_t aReadCount);
 
     // Helper for MultipleReadHelper that does not spin the event loop, so we
     // don't end up with nested event loops.
-    static void MultipleReadHelperInternal(nlTestSuite * apSuite, TestContext & aCtx, size_t aReadCount,
-                                           uint32_t & aNumSuccessCalls, uint32_t & aNumFailureCalls);
+    static void MultipleReadHelperInternal(TestContext * apCtx, size_t aReadCount, uint32_t & aNumSuccessCalls,
+                                           uint32_t & aNumFailureCalls);
 
     // Establish the given number of subscriptions, then issue the given number
     // of reads in parallel and wait for them all to succeed.
-    static void SubscribeThenReadHelper(nlTestSuite * apSuite, TestContext & aCtx, size_t aSubscribeCount, size_t aReadCount);
+    static void SubscribeThenReadHelper(TestContext * apCtx, size_t aSubscribeCount, size_t aReadCount);
 
     // Compute the amount of time it would take a subscription with a given
     // max-interval to time out.
@@ -348,9 +331,8 @@
     bool mAlterSubscriptionIntervals = false;
 };
 
-uint16_t TestReadInteraction::mMaxInterval = 66;
-
-TestReadInteraction gTestReadInteraction;
+TestContext * TestRead::mpContext = nullptr;
+uint16_t TestRead::mMaxInterval   = 66;
 
 class MockInteractionModelApp : public chip::app::ClusterStateCache::Callback
 {
@@ -401,29 +383,27 @@
     CHIP_ERROR mError         = CHIP_NO_ERROR;
 };
 
-void TestReadInteraction::TestReadAttributeResponse(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadAttributeResponse)
 {
-    TestContext & ctx       = *static_cast<TestContext *>(apContext);
-    auto sessionHandle      = ctx.GetSessionBobToAlice();
+    auto sessionHandle      = mpContext->GetSessionBobToAlice();
     bool onSuccessCbInvoked = false, onFailureCbInvoked = false;
 
     responseDirective = kSendDataResponse;
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onSuccessCb = [apSuite, &onSuccessCbInvoked](const app::ConcreteDataAttributePath & attributePath,
-                                                      const auto & dataResponse) {
+    auto onSuccessCb = [&onSuccessCbInvoked](const app::ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
         uint8_t i = 0;
-        NL_TEST_ASSERT(apSuite, attributePath.mDataVersion.HasValue() && attributePath.mDataVersion.Value() == kDataVersion);
+        EXPECT_TRUE(attributePath.mDataVersion.HasValue() && attributePath.mDataVersion.Value() == kDataVersion);
         auto iter = dataResponse.begin();
         while (iter.Next())
         {
             auto & item = iter.GetValue();
-            NL_TEST_ASSERT(apSuite, item.member1 == i);
+            EXPECT_EQ(item.member1, i);
             i++;
         }
-        NL_TEST_ASSERT(apSuite, i == 4);
-        NL_TEST_ASSERT(apSuite, iter.GetStatus() == CHIP_NO_ERROR);
+        EXPECT_EQ(i, 4u);
+        EXPECT_EQ(iter.GetStatus(), CHIP_NO_ERROR);
         onSuccessCbInvoked = true;
     };
 
@@ -434,19 +414,92 @@
     };
 
     Controller::ReadAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-        &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb);
+        &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, onSuccessCbInvoked && !onFailureCbInvoked);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients() == 0);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(onSuccessCbInvoked && !onFailureCbInvoked);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients(), 0u);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestReadInteraction::TestReadSubscribeAttributeResponseWithCache(nlTestSuite * apSuite, void * apContext)
+// NOTE: This test must execute before TestReadSubscribeAttributeResponseWithCache or else it will fail on
+// `EXPECT_TRUE(version1.HasValue() && (version1.Value() == 0))`.
+TEST_F(TestRead, TestReadSubscribeAttributeResponseWithVersionOnlyCache)
 {
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
+    CHIP_ERROR err    = CHIP_NO_ERROR;
+    responseDirective = kSendDataResponse;
+
+    MockInteractionModelApp delegate;
+    chip::app::ClusterStateCache cache(delegate, Optional<EventNumber>::Missing(), false /*cachedData*/);
+
+    chip::app::ReadPrepareParams readPrepareParams(mpContext->GetSessionBobToAlice());
+    //
+    // Test the application callback as well to ensure we get the right number of SubscriptionEstablishment/Termination
+    // callbacks.
+    //
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
+
+    // read of E2C2A* and E3C2A2. Expect cache E2C2 version
+    {
+        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(),
+                                   cache.GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
+        chip::app::AttributePathParams attributePathParams2[2];
+        attributePathParams2[0].mEndpointId  = chip::Test::kMockEndpoint2;
+        attributePathParams2[0].mClusterId   = chip::Test::MockClusterId(3);
+        attributePathParams2[0].mAttributeId = kInvalidAttributeId;
+
+        attributePathParams2[1].mEndpointId            = chip::Test::kMockEndpoint3;
+        attributePathParams2[1].mClusterId             = chip::Test::MockClusterId(2);
+        attributePathParams2[1].mAttributeId           = chip::Test::MockAttributeId(2);
+        readPrepareParams.mpAttributePathParamsList    = attributePathParams2;
+        readPrepareParams.mAttributePathParamsListSize = 2;
+        err                                            = readClient.SendRequest(readPrepareParams);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
+
+        mpContext->DrainAndServiceIO();
+        // There are supported 2 global and 3 non-global attributes in E2C2A* and  1 E3C2A2
+        EXPECT_EQ(delegate.mNumAttributeResponse, 6);
+        EXPECT_FALSE(delegate.mReadError);
+        Optional<DataVersion> version1;
+        app::ConcreteClusterPath clusterPath1(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3));
+        EXPECT_EQ(cache.GetVersion(clusterPath1, version1), CHIP_NO_ERROR);
+        EXPECT_TRUE(version1.HasValue() && (version1.Value() == 0));
+        Optional<DataVersion> version2;
+        app::ConcreteClusterPath clusterPath2(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2));
+        EXPECT_EQ(cache.GetVersion(clusterPath2, version2), CHIP_NO_ERROR);
+        EXPECT_FALSE(version2.HasValue());
+
+        {
+            app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
+                                                     chip::Test::MockAttributeId(2));
+            TLV::TLVReader reader;
+            EXPECT_NE(cache.Get(attributePath, reader), CHIP_NO_ERROR);
+        }
+
+        {
+            app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
+                                                     chip::Test::MockAttributeId(3));
+            TLV::TLVReader reader;
+            EXPECT_NE(cache.Get(attributePath, reader), CHIP_NO_ERROR);
+        }
+
+        {
+            app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2),
+                                                     chip::Test::MockAttributeId(2));
+            TLV::TLVReader reader;
+            EXPECT_NE(cache.Get(attributePath, reader), CHIP_NO_ERROR);
+        }
+        delegate.mNumAttributeResponse = 0;
+    }
+
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
+}
+
+TEST_F(TestRead, TestReadSubscribeAttributeResponseWithCache)
+{
     CHIP_ERROR err    = CHIP_NO_ERROR;
     responseDirective = kSendDataResponse;
 
@@ -461,14 +514,14 @@
         eventPathParam.mEventId    = 0;
     }
 
-    chip::app::ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice());
+    chip::app::ReadPrepareParams readPrepareParams(mpContext->GetSessionBobToAlice());
     readPrepareParams.mMinIntervalFloorSeconds   = 0;
     readPrepareParams.mMaxIntervalCeilingSeconds = 4;
     //
     // Test the application callback as well to ensure we get the right number of SubscriptionEstablishment/Termination
     // callbacks.
     //
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
 
     [[maybe_unused]] int testId = 0;
 
@@ -477,7 +530,7 @@
     {
         testId++;
         ChipLogProgress(DataManagement, "\t -- Running Read with ClusterStateCache Test ID %d", testId);
-        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(),
+        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(),
                                    cache.GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
         chip::app::AttributePathParams attributePathParams1[3];
         attributePathParams1[0].mEndpointId  = chip::Test::kMockEndpoint2;
@@ -495,15 +548,15 @@
         readPrepareParams.mpAttributePathParamsList    = attributePathParams1;
         readPrepareParams.mAttributePathParamsListSize = 3;
         err                                            = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 6);
-        NL_TEST_ASSERT(apSuite, !delegate.mReadError);
+        mpContext->DrainAndServiceIO();
+        EXPECT_EQ(delegate.mNumAttributeResponse, 6);
+        EXPECT_FALSE(delegate.mReadError);
         Optional<DataVersion> version1;
         app::ConcreteClusterPath clusterPath1(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath1, version1) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, !version1.HasValue());
+        EXPECT_EQ(cache.GetVersion(clusterPath1, version1), CHIP_NO_ERROR);
+        EXPECT_FALSE(version1.HasValue());
         delegate.mNumAttributeResponse = 0;
     }
 
@@ -512,7 +565,7 @@
     {
         testId++;
         ChipLogProgress(DataManagement, "\t -- Running Read with ClusterStateCache Test ID %d", testId);
-        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(),
+        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(),
                                    cache.GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
         chip::app::AttributePathParams attributePathParams1[3];
         attributePathParams1[0].mEndpointId  = chip::Test::kMockEndpoint2;
@@ -530,48 +583,48 @@
         readPrepareParams.mpAttributePathParamsList    = attributePathParams1;
         readPrepareParams.mAttributePathParamsListSize = 3;
         err                                            = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 3);
-        NL_TEST_ASSERT(apSuite, !delegate.mReadError);
+        mpContext->DrainAndServiceIO();
+        EXPECT_EQ(delegate.mNumAttributeResponse, 3);
+        EXPECT_FALSE(delegate.mReadError);
         Optional<DataVersion> version1;
         app::ConcreteClusterPath clusterPath1(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath1, version1) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, !version1.HasValue());
+        EXPECT_EQ(cache.GetVersion(clusterPath1, version1), CHIP_NO_ERROR);
+        EXPECT_FALSE(version1.HasValue());
         Optional<DataVersion> version2;
         app::ConcreteClusterPath clusterPath2(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath2, version2) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, !version2.HasValue());
+        EXPECT_EQ(cache.GetVersion(clusterPath2, version2), CHIP_NO_ERROR);
+        EXPECT_FALSE(version2.HasValue());
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(1));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             bool receivedAttribute1;
             reader.Get(receivedAttribute1);
-            NL_TEST_ASSERT(apSuite, receivedAttribute1 == expectedAttribute1);
+            EXPECT_EQ(receivedAttribute1, expectedAttribute1);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
 
         delegate.mNumAttributeResponse = 0;
@@ -583,7 +636,7 @@
     {
         testId++;
         ChipLogProgress(DataManagement, "\t -- Running Read with ClusterStateCache Test ID %d", testId);
-        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(),
+        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(),
                                    cache.GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
         chip::app::AttributePathParams attributePathParams1[3];
         attributePathParams1[0].mEndpointId  = kInvalidEndpointId;
@@ -601,45 +654,45 @@
         readPrepareParams.mpAttributePathParamsList    = attributePathParams1;
         readPrepareParams.mAttributePathParamsListSize = 3;
         err                                            = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2);
-        NL_TEST_ASSERT(apSuite, !delegate.mReadError);
+        mpContext->DrainAndServiceIO();
+        EXPECT_EQ(delegate.mNumAttributeResponse, 2);
+        EXPECT_FALSE(delegate.mReadError);
         Optional<DataVersion> version1;
         app::ConcreteClusterPath clusterPath1(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath1, version1) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, !version1.HasValue());
+        EXPECT_EQ(cache.GetVersion(clusterPath1, version1), CHIP_NO_ERROR);
+        EXPECT_FALSE(version1.HasValue());
         Optional<DataVersion> version2;
         app::ConcreteClusterPath clusterPath2(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath2, version2) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, !version2.HasValue());
+        EXPECT_EQ(cache.GetVersion(clusterPath2, version2), CHIP_NO_ERROR);
+        EXPECT_FALSE(version2.HasValue());
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint1, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) != CHIP_NO_ERROR);
+            EXPECT_NE(cache.Get(attributePath, reader), CHIP_NO_ERROR);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
         delegate.mNumAttributeResponse = 0;
     }
@@ -649,7 +702,7 @@
     {
         testId++;
         ChipLogProgress(DataManagement, "\t -- Running Read with ClusterStateCache Test ID %d", testId);
-        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(),
+        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(),
                                    cache.GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
         chip::app::AttributePathParams attributePathParams2[2];
         attributePathParams2[0].mEndpointId  = chip::Test::kMockEndpoint2;
@@ -662,59 +715,59 @@
         readPrepareParams.mpAttributePathParamsList    = attributePathParams2;
         readPrepareParams.mAttributePathParamsListSize = 2;
         err                                            = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
+        mpContext->DrainAndServiceIO();
         // There are supported 2 global and 3 non-global attributes in E2C2A* and  1 E3C2A2
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 6);
-        NL_TEST_ASSERT(apSuite, !delegate.mReadError);
+        EXPECT_EQ(delegate.mNumAttributeResponse, 6);
+        EXPECT_FALSE(delegate.mReadError);
         Optional<DataVersion> version1;
         app::ConcreteClusterPath clusterPath1(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath1, version1) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, version1.HasValue() && (version1.Value() == 0));
+        EXPECT_EQ(cache.GetVersion(clusterPath1, version1), CHIP_NO_ERROR);
+        EXPECT_TRUE(version1.HasValue() && (version1.Value() == 0));
         Optional<DataVersion> version2;
         app::ConcreteClusterPath clusterPath2(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath2, version2) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, !version2.HasValue());
+        EXPECT_EQ(cache.GetVersion(clusterPath2, version2), CHIP_NO_ERROR);
+        EXPECT_FALSE(version2.HasValue());
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(1));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             bool receivedAttribute1;
             reader.Get(receivedAttribute1);
-            NL_TEST_ASSERT(apSuite, receivedAttribute1 == expectedAttribute1);
+            EXPECT_EQ(receivedAttribute1, expectedAttribute1);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(3));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             uint64_t receivedAttribute3;
             reader.Get(receivedAttribute3);
-            NL_TEST_ASSERT(apSuite, receivedAttribute3 == expectedAttribute3);
+            EXPECT_EQ(receivedAttribute3, expectedAttribute3);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
         delegate.mNumAttributeResponse = 0;
     }
@@ -724,7 +777,7 @@
     {
         testId++;
         ChipLogProgress(DataManagement, "\t -- Running Read with ClusterStateCache Test ID %d", testId);
-        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(),
+        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(),
                                    cache.GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
         chip::app::AttributePathParams attributePathParams1[3];
         attributePathParams1[0].mEndpointId  = chip::Test::kMockEndpoint2;
@@ -742,48 +795,48 @@
         readPrepareParams.mpAttributePathParamsList    = attributePathParams1;
         readPrepareParams.mAttributePathParamsListSize = 3;
         err                                            = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 1);
-        NL_TEST_ASSERT(apSuite, !delegate.mReadError);
+        mpContext->DrainAndServiceIO();
+        EXPECT_EQ(delegate.mNumAttributeResponse, 1);
+        EXPECT_FALSE(delegate.mReadError);
         Optional<DataVersion> version1;
         app::ConcreteClusterPath clusterPath1(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath1, version1) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, version1.HasValue() && (version1.Value() == 0));
+        EXPECT_EQ(cache.GetVersion(clusterPath1, version1), CHIP_NO_ERROR);
+        EXPECT_TRUE(version1.HasValue() && (version1.Value() == 0));
         Optional<DataVersion> version2;
         app::ConcreteClusterPath clusterPath2(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath2, version2) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, !version2.HasValue());
+        EXPECT_EQ(cache.GetVersion(clusterPath2, version2), CHIP_NO_ERROR);
+        EXPECT_FALSE(version2.HasValue());
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(1));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             bool receivedAttribute1;
             reader.Get(receivedAttribute1);
-            NL_TEST_ASSERT(apSuite, receivedAttribute1 == expectedAttribute1);
+            EXPECT_EQ(receivedAttribute1, expectedAttribute1);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
         delegate.mNumAttributeResponse = 0;
     }
@@ -793,7 +846,7 @@
     {
         testId++;
         ChipLogProgress(DataManagement, "\t -- Running Read with ClusterStateCache Test ID %d", testId);
-        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(),
+        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(),
                                    cache.GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
         chip::app::AttributePathParams attributePathParams2[2];
         attributePathParams2[0].mEndpointId  = chip::Test::kMockEndpoint2;
@@ -806,58 +859,58 @@
         readPrepareParams.mpAttributePathParamsList    = attributePathParams2;
         readPrepareParams.mAttributePathParamsListSize = 2;
         err                                            = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 1);
-        NL_TEST_ASSERT(apSuite, !delegate.mReadError);
+        mpContext->DrainAndServiceIO();
+        EXPECT_EQ(delegate.mNumAttributeResponse, 1);
+        EXPECT_FALSE(delegate.mReadError);
         Optional<DataVersion> version1;
         app::ConcreteClusterPath clusterPath1(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath1, version1) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, version1.HasValue() && (version1.Value() == 0));
+        EXPECT_EQ(cache.GetVersion(clusterPath1, version1), CHIP_NO_ERROR);
+        EXPECT_TRUE(version1.HasValue() && (version1.Value() == 0));
         Optional<DataVersion> version2;
         app::ConcreteClusterPath clusterPath2(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath2, version2) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, !version2.HasValue());
+        EXPECT_EQ(cache.GetVersion(clusterPath2, version2), CHIP_NO_ERROR);
+        EXPECT_FALSE(version2.HasValue());
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(1));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             bool receivedAttribute1;
             reader.Get(receivedAttribute1);
-            NL_TEST_ASSERT(apSuite, receivedAttribute1 == expectedAttribute1);
+            EXPECT_EQ(receivedAttribute1, expectedAttribute1);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(3));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             uint64_t receivedAttribute3;
             reader.Get(receivedAttribute3);
-            NL_TEST_ASSERT(apSuite, receivedAttribute3 == expectedAttribute3);
+            EXPECT_EQ(receivedAttribute3, expectedAttribute3);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
         delegate.mNumAttributeResponse = 0;
     }
@@ -870,7 +923,7 @@
     {
         testId++;
         ChipLogProgress(DataManagement, "\t -- Running Read with ClusterStateCache Test ID %d", testId);
-        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(),
+        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(),
                                    cache.GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
         chip::app::AttributePathParams attributePathParams1[3];
         attributePathParams1[0].mEndpointId  = chip::Test::kMockEndpoint2;
@@ -888,48 +941,48 @@
         readPrepareParams.mpAttributePathParamsList    = attributePathParams1;
         readPrepareParams.mAttributePathParamsListSize = 3;
         err                                            = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 3);
-        NL_TEST_ASSERT(apSuite, !delegate.mReadError);
+        mpContext->DrainAndServiceIO();
+        EXPECT_EQ(delegate.mNumAttributeResponse, 3);
+        EXPECT_FALSE(delegate.mReadError);
         Optional<DataVersion> version1;
         app::ConcreteClusterPath clusterPath1(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath1, version1) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, !version1.HasValue());
+        EXPECT_EQ(cache.GetVersion(clusterPath1, version1), CHIP_NO_ERROR);
+        EXPECT_FALSE(version1.HasValue());
         Optional<DataVersion> version2;
         app::ConcreteClusterPath clusterPath2(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath2, version2) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, !version2.HasValue());
+        EXPECT_EQ(cache.GetVersion(clusterPath2, version2), CHIP_NO_ERROR);
+        EXPECT_FALSE(version2.HasValue());
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(1));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             bool receivedAttribute1;
             reader.Get(receivedAttribute1);
-            NL_TEST_ASSERT(apSuite, receivedAttribute1 == expectedAttribute1);
+            EXPECT_EQ(receivedAttribute1, expectedAttribute1);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
         delegate.mNumAttributeResponse = 0;
     }
@@ -939,7 +992,7 @@
     {
         testId++;
         ChipLogProgress(DataManagement, "\t -- Running Read with ClusterStateCache Test ID %d", testId);
-        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(),
+        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(),
                                    cache.GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
         chip::app::AttributePathParams attributePathParams1[3];
         attributePathParams1[0].mEndpointId  = chip::Test::kMockEndpoint2;
@@ -957,48 +1010,48 @@
         readPrepareParams.mpAttributePathParamsList    = attributePathParams1;
         readPrepareParams.mAttributePathParamsListSize = 3;
         err                                            = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 3);
-        NL_TEST_ASSERT(apSuite, !delegate.mReadError);
+        mpContext->DrainAndServiceIO();
+        EXPECT_EQ(delegate.mNumAttributeResponse, 3);
+        EXPECT_FALSE(delegate.mReadError);
         Optional<DataVersion> version1;
         app::ConcreteClusterPath clusterPath1(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath1, version1) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, !version1.HasValue());
+        EXPECT_EQ(cache.GetVersion(clusterPath1, version1), CHIP_NO_ERROR);
+        EXPECT_FALSE(version1.HasValue());
         Optional<DataVersion> version2;
         app::ConcreteClusterPath clusterPath2(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath2, version2) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, !version2.HasValue());
+        EXPECT_EQ(cache.GetVersion(clusterPath2, version2), CHIP_NO_ERROR);
+        EXPECT_FALSE(version2.HasValue());
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(1));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             bool receivedAttribute1;
             reader.Get(receivedAttribute1);
-            NL_TEST_ASSERT(apSuite, receivedAttribute1 == expectedAttribute1);
+            EXPECT_EQ(receivedAttribute1, expectedAttribute1);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
         delegate.mNumAttributeResponse = 0;
     }
@@ -1008,7 +1061,7 @@
     {
         testId++;
         ChipLogProgress(DataManagement, "\t -- Running Read with ClusterStateCache Test ID %d", testId);
-        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(),
+        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(),
                                    cache.GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
         chip::app::AttributePathParams attributePathParams2[2];
         attributePathParams2[0].mEndpointId  = chip::Test::kMockEndpoint2;
@@ -1021,58 +1074,58 @@
         readPrepareParams.mpAttributePathParamsList    = attributePathParams2;
         readPrepareParams.mAttributePathParamsListSize = 2;
         err                                            = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 6);
-        NL_TEST_ASSERT(apSuite, !delegate.mReadError);
+        mpContext->DrainAndServiceIO();
+        EXPECT_EQ(delegate.mNumAttributeResponse, 6);
+        EXPECT_FALSE(delegate.mReadError);
         Optional<DataVersion> version1;
         app::ConcreteClusterPath clusterPath1(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath1, version1) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, version1.HasValue() && (version1.Value() == 1));
+        EXPECT_EQ(cache.GetVersion(clusterPath1, version1), CHIP_NO_ERROR);
+        EXPECT_TRUE(version1.HasValue() && (version1.Value() == 1));
         Optional<DataVersion> version2;
         app::ConcreteClusterPath clusterPath2(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath2, version2) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, !version2.HasValue());
+        EXPECT_EQ(cache.GetVersion(clusterPath2, version2), CHIP_NO_ERROR);
+        EXPECT_FALSE(version2.HasValue());
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(1));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             bool receivedAttribute1;
             reader.Get(receivedAttribute1);
-            NL_TEST_ASSERT(apSuite, receivedAttribute1 == expectedAttribute1);
+            EXPECT_EQ(receivedAttribute1, expectedAttribute1);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(3));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             uint64_t receivedAttribute3;
             reader.Get(receivedAttribute3);
-            NL_TEST_ASSERT(apSuite, receivedAttribute3 == expectedAttribute3);
+            EXPECT_EQ(receivedAttribute3, expectedAttribute3);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
         delegate.mNumAttributeResponse = 0;
     }
@@ -1083,7 +1136,7 @@
     {
         testId++;
         ChipLogProgress(DataManagement, "\t -- Running Read with ClusterStateCache Test ID %d", testId);
-        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(),
+        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(),
                                    cache.GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
         chip::app::AttributePathParams attributePathParams2[2];
         attributePathParams2[0].mEndpointId  = chip::Test::kMockEndpoint2;
@@ -1104,58 +1157,58 @@
         readPrepareParams.mEventPathParamsListSize = 75;
 
         err = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 6);
-        NL_TEST_ASSERT(apSuite, !delegate.mReadError);
+        mpContext->DrainAndServiceIO();
+        EXPECT_EQ(delegate.mNumAttributeResponse, 6);
+        EXPECT_FALSE(delegate.mReadError);
         Optional<DataVersion> version1;
         app::ConcreteClusterPath clusterPath1(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath1, version1) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, version1.HasValue() && (version1.Value() == 1));
+        EXPECT_EQ(cache.GetVersion(clusterPath1, version1), CHIP_NO_ERROR);
+        EXPECT_TRUE(version1.HasValue() && (version1.Value() == 1));
         Optional<DataVersion> version2;
         app::ConcreteClusterPath clusterPath2(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath2, version2) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, !version2.HasValue());
+        EXPECT_EQ(cache.GetVersion(clusterPath2, version2), CHIP_NO_ERROR);
+        EXPECT_FALSE(version2.HasValue());
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(1));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             bool receivedAttribute1;
             reader.Get(receivedAttribute1);
-            NL_TEST_ASSERT(apSuite, receivedAttribute1 == expectedAttribute1);
+            EXPECT_EQ(receivedAttribute1, expectedAttribute1);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(3));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             uint64_t receivedAttribute3;
             reader.Get(receivedAttribute3);
-            NL_TEST_ASSERT(apSuite, receivedAttribute3 == expectedAttribute3);
+            EXPECT_EQ(receivedAttribute3, expectedAttribute3);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
         delegate.mNumAttributeResponse             = 0;
         readPrepareParams.mpEventPathParamsList    = nullptr;
@@ -1169,7 +1222,7 @@
     {
         testId++;
         ChipLogProgress(DataManagement, "\t -- Running Read with ClusterStateCache Test ID %d", testId);
-        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(),
+        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(),
                                    cache.GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
 
         chip::app::AttributePathParams attributePathParams3[3];
@@ -1188,82 +1241,82 @@
         readPrepareParams.mAttributePathParamsListSize = 3;
 
         err = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
+        mpContext->DrainAndServiceIO();
         // E1C2A* has 3 attributes and E2C3A* has 5 attributes and E2C2A* has 4 attributes
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 12);
-        NL_TEST_ASSERT(apSuite, !delegate.mReadError);
+        EXPECT_EQ(delegate.mNumAttributeResponse, 12);
+        EXPECT_FALSE(delegate.mReadError);
         Optional<DataVersion> version1;
         app::ConcreteClusterPath clusterPath1(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath1, version1) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, version1.HasValue() && (version1.Value() == 2));
+        EXPECT_EQ(cache.GetVersion(clusterPath1, version1), CHIP_NO_ERROR);
+        EXPECT_TRUE(version1.HasValue() && (version1.Value() == 2));
         Optional<DataVersion> version2;
         app::ConcreteClusterPath clusterPath2(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(2));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath2, version2) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, version2.HasValue() && (version2.Value() == 2));
+        EXPECT_EQ(cache.GetVersion(clusterPath2, version2), CHIP_NO_ERROR);
+        EXPECT_TRUE(version2.HasValue() && (version2.Value() == 2));
         Optional<DataVersion> version3;
         app::ConcreteClusterPath clusterPath3(chip::Test::kMockEndpoint1, chip::Test::MockClusterId(2));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath3, version3) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, version3.HasValue() && (version3.Value() == 2));
+        EXPECT_EQ(cache.GetVersion(clusterPath3, version3), CHIP_NO_ERROR);
+        EXPECT_TRUE(version3.HasValue() && (version3.Value() == 2));
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint1, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(1));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             bool receivedAttribute1;
             reader.Get(receivedAttribute1);
-            NL_TEST_ASSERT(apSuite, receivedAttribute1 == expectedAttribute1);
+            EXPECT_EQ(receivedAttribute1, expectedAttribute1);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(1));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             bool receivedAttribute1;
             reader.Get(receivedAttribute1);
-            NL_TEST_ASSERT(apSuite, receivedAttribute1 == expectedAttribute1);
+            EXPECT_EQ(receivedAttribute1, expectedAttribute1);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(3));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             uint64_t receivedAttribute3;
             reader.Get(receivedAttribute3);
-            NL_TEST_ASSERT(apSuite, receivedAttribute3 == expectedAttribute3);
+            EXPECT_EQ(receivedAttribute3, expectedAttribute3);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(1));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             bool receivedAttribute1;
             reader.Get(receivedAttribute1);
-            NL_TEST_ASSERT(apSuite, receivedAttribute1 == expectedAttribute1);
+            EXPECT_EQ(receivedAttribute1, expectedAttribute1);
         }
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
 
         delegate.mNumAttributeResponse = 0;
@@ -1276,7 +1329,7 @@
     {
         testId++;
         ChipLogProgress(DataManagement, "\t -- Running Read with ClusterStateCache Test ID %d", testId);
-        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(),
+        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(),
                                    cache.GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
 
         chip::app::AttributePathParams attributePathParams3[3];
@@ -1300,82 +1353,82 @@
         static_assert(73 <= ArraySize(eventPathParams));
         readPrepareParams.mEventPathParamsListSize = 73;
         err                                        = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 7);
-        NL_TEST_ASSERT(apSuite, !delegate.mReadError);
+        mpContext->DrainAndServiceIO();
+        EXPECT_EQ(delegate.mNumAttributeResponse, 7);
+        EXPECT_FALSE(delegate.mReadError);
         Optional<DataVersion> version1;
         app::ConcreteClusterPath clusterPath1(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath1, version1) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, version1.HasValue() && (version1.Value() == 2));
+        EXPECT_EQ(cache.GetVersion(clusterPath1, version1), CHIP_NO_ERROR);
+        EXPECT_TRUE(version1.HasValue() && (version1.Value() == 2));
         Optional<DataVersion> version2;
         app::ConcreteClusterPath clusterPath2(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(2));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath2, version2) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, version2.HasValue() && (version2.Value() == 2));
+        EXPECT_EQ(cache.GetVersion(clusterPath2, version2), CHIP_NO_ERROR);
+        EXPECT_TRUE(version2.HasValue() && (version2.Value() == 2));
         Optional<DataVersion> version3;
         app::ConcreteClusterPath clusterPath3(chip::Test::kMockEndpoint1, chip::Test::MockClusterId(2));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath3, version3) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, version3.HasValue() && (version3.Value() == 2));
+        EXPECT_EQ(cache.GetVersion(clusterPath3, version3), CHIP_NO_ERROR);
+        EXPECT_TRUE(version3.HasValue() && (version3.Value() == 2));
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint1, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(1));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             bool receivedAttribute1;
             reader.Get(receivedAttribute1);
-            NL_TEST_ASSERT(apSuite, receivedAttribute1 == expectedAttribute1);
+            EXPECT_EQ(receivedAttribute1, expectedAttribute1);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(1));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             bool receivedAttribute1;
             reader.Get(receivedAttribute1);
-            NL_TEST_ASSERT(apSuite, receivedAttribute1 == expectedAttribute1);
+            EXPECT_EQ(receivedAttribute1, expectedAttribute1);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
                                                      chip::Test::MockAttributeId(3));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             uint64_t receivedAttribute3;
             reader.Get(receivedAttribute3);
-            NL_TEST_ASSERT(apSuite, receivedAttribute3 == expectedAttribute3);
+            EXPECT_EQ(receivedAttribute3, expectedAttribute3);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(1));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             bool receivedAttribute1;
             reader.Get(receivedAttribute1);
-            NL_TEST_ASSERT(apSuite, receivedAttribute1 == expectedAttribute1);
+            EXPECT_EQ(receivedAttribute1, expectedAttribute1);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
         delegate.mNumAttributeResponse             = 0;
         readPrepareParams.mpEventPathParamsList    = nullptr;
@@ -1387,7 +1440,7 @@
     {
         testId++;
         ChipLogProgress(DataManagement, "\t -- Running Read with ClusterStateCache Test ID %d", testId);
-        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(),
+        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(),
                                    cache.GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
         chip::app::AttributePathParams attributePathParams1[1];
         attributePathParams1[0].mEndpointId = chip::Test::kMockEndpoint3;
@@ -1396,147 +1449,72 @@
         readPrepareParams.mpAttributePathParamsList    = attributePathParams1;
         readPrepareParams.mAttributePathParamsListSize = 1;
         err                                            = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 6);
-        NL_TEST_ASSERT(apSuite, !delegate.mReadError);
+        mpContext->DrainAndServiceIO();
+        EXPECT_EQ(delegate.mNumAttributeResponse, 6);
+        EXPECT_FALSE(delegate.mReadError);
         Optional<DataVersion> version1;
         app::ConcreteClusterPath clusterPath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2));
 
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath, version1) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, version1.HasValue());
+        EXPECT_EQ(cache.GetVersion(clusterPath, version1), CHIP_NO_ERROR);
+        EXPECT_TRUE(version1.HasValue());
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(1));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             bool receivedAttribute1;
             reader.Get(receivedAttribute1);
-            NL_TEST_ASSERT(apSuite, receivedAttribute1 == expectedAttribute1);
+            EXPECT_EQ(receivedAttribute1, expectedAttribute1);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(2));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             int16_t receivedAttribute2;
             reader.Get(receivedAttribute2);
-            NL_TEST_ASSERT(apSuite, receivedAttribute2 == expectedAttribute2);
+            EXPECT_EQ(receivedAttribute2, expectedAttribute2);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(3));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             uint64_t receivedAttribute3;
             reader.Get(receivedAttribute3);
-            NL_TEST_ASSERT(apSuite, receivedAttribute3 == expectedAttribute3);
+            EXPECT_EQ(receivedAttribute3, expectedAttribute3);
         }
 
         {
             app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2),
                                                      chip::Test::MockAttributeId(4));
             TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) == CHIP_NO_ERROR);
+            EXPECT_EQ(cache.Get(attributePath, reader), CHIP_NO_ERROR);
             uint8_t receivedAttribute4[256];
             reader.GetBytes(receivedAttribute4, 256);
-            NL_TEST_ASSERT(apSuite, memcmp(receivedAttribute4, expectedAttribute4, 256));
+            EXPECT_TRUE(memcmp(receivedAttribute4, expectedAttribute4, 256));
         }
         delegate.mNumAttributeResponse = 0;
     }
 
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestReadInteraction::TestReadSubscribeAttributeResponseWithVersionOnlyCache(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadEventResponse)
 {
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
-    CHIP_ERROR err    = CHIP_NO_ERROR;
-    responseDirective = kSendDataResponse;
-
-    MockInteractionModelApp delegate;
-    chip::app::ClusterStateCache cache(delegate, Optional<EventNumber>::Missing(), false /*cachedData*/);
-
-    chip::app::ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice());
-    //
-    // Test the application callback as well to ensure we get the right number of SubscriptionEstablishment/Termination
-    // callbacks.
-    //
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
-
-    // read of E2C2A* and E3C2A2. Expect cache E2C2 version
-    {
-        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(),
-                                   cache.GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
-        chip::app::AttributePathParams attributePathParams2[2];
-        attributePathParams2[0].mEndpointId  = chip::Test::kMockEndpoint2;
-        attributePathParams2[0].mClusterId   = chip::Test::MockClusterId(3);
-        attributePathParams2[0].mAttributeId = kInvalidAttributeId;
-
-        attributePathParams2[1].mEndpointId            = chip::Test::kMockEndpoint3;
-        attributePathParams2[1].mClusterId             = chip::Test::MockClusterId(2);
-        attributePathParams2[1].mAttributeId           = chip::Test::MockAttributeId(2);
-        readPrepareParams.mpAttributePathParamsList    = attributePathParams2;
-        readPrepareParams.mAttributePathParamsListSize = 2;
-        err                                            = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
-
-        ctx.DrainAndServiceIO();
-        // There are supported 2 global and 3 non-global attributes in E2C2A* and  1 E3C2A2
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 6);
-        NL_TEST_ASSERT(apSuite, !delegate.mReadError);
-        Optional<DataVersion> version1;
-        app::ConcreteClusterPath clusterPath1(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath1, version1) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, version1.HasValue() && (version1.Value() == 0));
-        Optional<DataVersion> version2;
-        app::ConcreteClusterPath clusterPath2(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2));
-        NL_TEST_ASSERT(apSuite, cache.GetVersion(clusterPath2, version2) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, !version2.HasValue());
-
-        {
-            app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
-                                                     chip::Test::MockAttributeId(2));
-            TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) != CHIP_NO_ERROR);
-        }
-
-        {
-            app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint2, chip::Test::MockClusterId(3),
-                                                     chip::Test::MockAttributeId(3));
-            TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) != CHIP_NO_ERROR);
-        }
-
-        {
-            app::ConcreteAttributePath attributePath(chip::Test::kMockEndpoint3, chip::Test::MockClusterId(2),
-                                                     chip::Test::MockAttributeId(2));
-            TLV::TLVReader reader;
-            NL_TEST_ASSERT(apSuite, cache.Get(attributePath, reader) != CHIP_NO_ERROR);
-        }
-        delegate.mNumAttributeResponse = 0;
-    }
-
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
-}
-
-void TestReadInteraction::TestReadEventResponse(nlTestSuite * apSuite, void * apContext)
-{
-    TestContext & ctx       = *static_cast<TestContext *>(apContext);
-    auto sessionHandle      = ctx.GetSessionBobToAlice();
+    auto sessionHandle      = mpContext->GetSessionBobToAlice();
     bool onSuccessCbInvoked = false, onFailureCbInvoked = false, onDoneCbInvoked = false;
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onSuccessCb = [apSuite, &onSuccessCbInvoked](const app::EventHeader & eventHeader, const auto & EventResponse) {
+    auto onSuccessCb = [&onSuccessCbInvoked](const app::EventHeader & eventHeader, const auto & EventResponse) {
         // TODO: Need to add check when IM event server integration completes
-        IgnoreUnusedVariable(apSuite);
         onSuccessCbInvoked = true;
     };
 
@@ -1549,22 +1527,21 @@
     auto onDoneCb = [&onDoneCbInvoked](app::ReadClient * apReadClient) { onDoneCbInvoked = true; };
 
     Controller::ReadEvent<Clusters::UnitTesting::Events::TestEvent::DecodableType>(
-        &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, onDoneCb);
+        &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, onDoneCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, !onFailureCbInvoked);
-    NL_TEST_ASSERT(apSuite, onDoneCbInvoked);
+    EXPECT_FALSE(onFailureCbInvoked);
+    EXPECT_TRUE(onDoneCbInvoked);
 
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients() == 0);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients(), 0u);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestReadInteraction::TestReadAttributeError(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadAttributeError)
 {
-    TestContext & ctx       = *static_cast<TestContext *>(apContext);
-    auto sessionHandle      = ctx.GetSessionBobToAlice();
+    auto sessionHandle      = mpContext->GetSessionBobToAlice();
     bool onSuccessCbInvoked = false, onFailureCbInvoked = false;
 
     responseDirective = kSendDataError;
@@ -1577,26 +1554,25 @@
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onFailureCb = [&onFailureCbInvoked, apSuite](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) {
-        NL_TEST_ASSERT(apSuite, aError.IsIMStatus() && app::StatusIB(aError).mStatus == Protocols::InteractionModel::Status::Busy);
+    auto onFailureCb = [&onFailureCbInvoked](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) {
+        EXPECT_TRUE(aError.IsIMStatus() && app::StatusIB(aError).mStatus == Protocols::InteractionModel::Status::Busy);
         onFailureCbInvoked = true;
     };
 
     Controller::ReadAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-        &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb);
+        &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, !onSuccessCbInvoked && onFailureCbInvoked);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients() == 0);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(!onSuccessCbInvoked && onFailureCbInvoked);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients(), 0u);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestReadInteraction::TestReadAttributeTimeout(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadAttributeTimeout)
 {
-    TestContext & ctx       = *static_cast<TestContext *>(apContext);
-    auto sessionHandle      = ctx.GetSessionBobToAlice();
+    auto sessionHandle      = mpContext->GetSessionBobToAlice();
     bool onSuccessCbInvoked = false, onFailureCbInvoked = false;
 
     responseDirective = kSendDataError;
@@ -1609,38 +1585,38 @@
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onFailureCb = [&onFailureCbInvoked, apSuite](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) {
-        NL_TEST_ASSERT(apSuite, aError == CHIP_ERROR_TIMEOUT);
+    auto onFailureCb = [&onFailureCbInvoked](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) {
+        EXPECT_EQ(aError, CHIP_ERROR_TIMEOUT);
         onFailureCbInvoked = true;
     };
 
     Controller::ReadAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-        &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb);
+        &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb);
 
-    ctx.ExpireSessionAliceToBob();
+    mpContext->ExpireSessionAliceToBob();
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 1);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 1u);
 
-    ctx.ExpireSessionBobToAlice();
+    mpContext->ExpireSessionBobToAlice();
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, !onSuccessCbInvoked && onFailureCbInvoked);
+    EXPECT_TRUE(!onSuccessCbInvoked && onFailureCbInvoked);
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == 0);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), 0u);
 
     //
     // Let's put back the sessions so that the next tests (which assume a valid initialized set of sessions)
     // can function correctly.
     //
-    ctx.CreateSessionAliceToBob();
-    ctx.CreateSessionBobToAlice();
+    mpContext->CreateSessionAliceToBob();
+    mpContext->CreateSessionBobToAlice();
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
 class TestResubscriptionCallback : public app::ReadClient::Callback
@@ -1699,21 +1675,20 @@
 // TODO: This does not validate the CASE establishment pathways since we're limited by the PASE-centric TestContext.
 //
 //
-void TestReadInteraction::TestResubscribeAttributeTimeout(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestResubscribeAttributeTimeout)
 {
-    TestContext & ctx  = *static_cast<TestContext *>(apContext);
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
-    ctx.SetMRPMode(chip::Test::MessagingContext::MRPMode::kResponsive);
+    mpContext->SetMRPMode(chip::Test::MessagingContext::MRPMode::kResponsive);
 
     {
         TestResubscriptionCallback callback;
-        app::ReadClient readClient(app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(), callback,
+        app::ReadClient readClient(app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(), callback,
                                    app::ReadClient::InteractionType::Subscribe);
 
         callback.SetReadClient(&readClient);
 
-        app::ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice());
+        app::ReadPrepareParams readPrepareParams(mpContext->GetSessionBobToAlice());
 
         // Read full wildcard paths, repeat twice to ensure chunking.
         app::AttributePathParams attributePathParams[1];
@@ -1728,16 +1703,16 @@
         readPrepareParams.mMaxIntervalCeilingSeconds = maxIntervalCeilingSeconds;
 
         auto err = readClient.SendAutoResubscribeRequest(std::move(readPrepareParams));
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
         //
         // Drive servicing IO till we have established a subscription.
         //
-        ctx.GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
-                                        [&]() { return callback.mOnSubscriptionEstablishedCount >= 1; });
-        NL_TEST_ASSERT(apSuite, callback.mOnSubscriptionEstablishedCount == 1);
-        NL_TEST_ASSERT(apSuite, callback.mOnError == 0);
-        NL_TEST_ASSERT(apSuite, callback.mOnResubscriptionsAttempted == 0);
+        mpContext->GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
+                                               [&]() { return callback.mOnSubscriptionEstablishedCount >= 1; });
+        EXPECT_EQ(callback.mOnSubscriptionEstablishedCount, 1);
+        EXPECT_EQ(callback.mOnError, 0);
+        EXPECT_EQ(callback.mOnResubscriptionsAttempted, 0);
 
         chip::app::ReadHandler * readHandler = app::InteractionModelEngine::GetInstance()->ActiveHandlerAt(0);
 
@@ -1749,55 +1724,54 @@
         // Disable packet transmission, and drive IO till we have reported a re-subscription attempt.
         //
         //
-        ctx.GetLoopback().mNumMessagesToDrop = chip::Test::LoopbackTransport::kUnlimitedMessageCount;
-        ctx.GetIOContext().DriveIOUntil(ComputeSubscriptionTimeout(System::Clock::Seconds16(maxInterval)),
-                                        [&]() { return callback.mOnResubscriptionsAttempted > 0; });
+        mpContext->GetLoopback().mNumMessagesToDrop = chip::Test::LoopbackTransport::kUnlimitedMessageCount;
+        mpContext->GetIOContext().DriveIOUntil(ComputeSubscriptionTimeout(System::Clock::Seconds16(maxInterval)),
+                                               [&]() { return callback.mOnResubscriptionsAttempted > 0; });
 
-        NL_TEST_ASSERT(apSuite, callback.mOnResubscriptionsAttempted == 1);
-        NL_TEST_ASSERT(apSuite, callback.mLastError == CHIP_ERROR_TIMEOUT);
+        EXPECT_EQ(callback.mOnResubscriptionsAttempted, 1);
+        EXPECT_EQ(callback.mLastError, CHIP_ERROR_TIMEOUT);
 
-        ctx.GetLoopback().mNumMessagesToDrop = 0;
+        mpContext->GetLoopback().mNumMessagesToDrop = 0;
         callback.ClearCounters();
 
         //
         // Drive servicing IO till we have established a subscription.
         //
-        ctx.GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
-                                        [&]() { return callback.mOnSubscriptionEstablishedCount == 1; });
-        NL_TEST_ASSERT(apSuite, callback.mOnSubscriptionEstablishedCount == 1);
+        mpContext->GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
+                                               [&]() { return callback.mOnSubscriptionEstablishedCount == 1; });
+        EXPECT_EQ(callback.mOnSubscriptionEstablishedCount, 1);
 
         //
         // With re-sub enabled, we shouldn't have encountered any errors
         //
-        NL_TEST_ASSERT(apSuite, callback.mOnError == 0);
-        NL_TEST_ASSERT(apSuite, callback.mOnDone == 0);
+        EXPECT_EQ(callback.mOnError, 0);
+        EXPECT_EQ(callback.mOnDone, 0);
     }
 
-    ctx.SetMRPMode(chip::Test::MessagingContext::MRPMode::kDefault);
+    mpContext->SetMRPMode(chip::Test::MessagingContext::MRPMode::kDefault);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
 //
 // This validates a vanilla subscription with re-susbcription disabled timing out correctly on the client
 // side and triggering the OnError callback with the right error code.
 //
-void TestReadInteraction::TestSubscribeAttributeTimeout(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestSubscribeAttributeTimeout)
 {
-    TestContext & ctx  = *static_cast<TestContext *>(apContext);
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
-    ctx.SetMRPMode(chip::Test::MessagingContext::MRPMode::kResponsive);
+    mpContext->SetMRPMode(chip::Test::MessagingContext::MRPMode::kResponsive);
 
     {
         TestResubscriptionCallback callback;
-        app::ReadClient readClient(app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(), callback,
+        app::ReadClient readClient(app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(), callback,
                                    app::ReadClient::InteractionType::Subscribe);
 
         callback.SetReadClient(&readClient);
 
-        app::ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice());
+        app::ReadPrepareParams readPrepareParams(mpContext->GetSessionBobToAlice());
 
         app::AttributePathParams attributePathParams[1];
         readPrepareParams.mpAttributePathParamsList    = attributePathParams;
@@ -1813,19 +1787,19 @@
         readPrepareParams.mMaxIntervalCeilingSeconds = maxIntervalCeilingSeconds;
 
         auto err = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
         //
         // Drive servicing IO till we have established a subscription.
         //
-        ctx.GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
-                                        [&]() { return callback.mOnSubscriptionEstablishedCount >= 1; });
-        NL_TEST_ASSERT(apSuite, callback.mOnSubscriptionEstablishedCount == 1);
+        mpContext->GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
+                                               [&]() { return callback.mOnSubscriptionEstablishedCount >= 1; });
+        EXPECT_EQ(callback.mOnSubscriptionEstablishedCount, 1);
 
         //
         // Request we drop all further messages.
         //
-        ctx.GetLoopback().mNumMessagesToDrop = chip::Test::LoopbackTransport::kUnlimitedMessageCount;
+        mpContext->GetLoopback().mNumMessagesToDrop = chip::Test::LoopbackTransport::kUnlimitedMessageCount;
 
         chip::app::ReadHandler * readHandler = app::InteractionModelEngine::GetInstance()->ActiveHandlerAt(0);
 
@@ -1838,26 +1812,25 @@
         // by the liveness timer firing once we hit our max-interval plus
         // retransmit timeouts.
         //
-        ctx.GetIOContext().DriveIOUntil(ComputeSubscriptionTimeout(System::Clock::Seconds16(maxInterval)),
-                                        [&]() { return callback.mOnError >= 1; });
+        mpContext->GetIOContext().DriveIOUntil(ComputeSubscriptionTimeout(System::Clock::Seconds16(maxInterval)),
+                                               [&]() { return callback.mOnError >= 1; });
 
-        NL_TEST_ASSERT(apSuite, callback.mOnError == 1);
-        NL_TEST_ASSERT(apSuite, callback.mLastError == CHIP_ERROR_TIMEOUT);
-        NL_TEST_ASSERT(apSuite, callback.mOnDone == 1);
-        NL_TEST_ASSERT(apSuite, callback.mOnResubscriptionsAttempted == 0);
+        EXPECT_EQ(callback.mOnError, 1);
+        EXPECT_EQ(callback.mLastError, CHIP_ERROR_TIMEOUT);
+        EXPECT_EQ(callback.mOnDone, 1);
+        EXPECT_EQ(callback.mOnResubscriptionsAttempted, 0);
     }
 
-    ctx.SetMRPMode(chip::Test::MessagingContext::MRPMode::kDefault);
+    mpContext->SetMRPMode(chip::Test::MessagingContext::MRPMode::kDefault);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
-    ctx.GetLoopback().mNumMessagesToDrop = 0;
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
+    mpContext->GetLoopback().mNumMessagesToDrop = 0;
 }
 
-void TestReadInteraction::TestReadHandler_MultipleSubscriptions(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_MultipleSubscriptions)
 {
-    TestContext & ctx                        = *static_cast<TestContext *>(apContext);
-    auto sessionHandle                       = ctx.GetSessionBobToAlice();
+    auto sessionHandle                       = mpContext->GetSessionBobToAlice();
     uint32_t numSuccessCalls                 = 0;
     uint32_t numSubscriptionEstablishedCalls = 0;
 
@@ -1871,11 +1844,11 @@
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onFailureCb = [&apSuite](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) {
+    auto onFailureCb = [](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) {
         //
         // We shouldn't be encountering any failures in this test.
         //
-        NL_TEST_ASSERT(apSuite, false);
+        EXPECT_TRUE(false);
     };
 
     auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls](const app::ReadClient & readClient,
@@ -1887,7 +1860,7 @@
     // Test the application callback as well to ensure we get the right number of SubscriptionEstablishment/Termination
     // callbacks.
     //
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
 
     //
     // Try to issue parallel subscriptions that will exceed the value for app::InteractionModelEngine::kReadHandlerPoolSize.
@@ -1896,37 +1869,35 @@
     //
     for (size_t i = 0; i < (app::InteractionModelEngine::kReadHandlerPoolSize + 1); i++)
     {
-        NL_TEST_ASSERT(apSuite,
-                       Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-                           &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 20,
-                           onSubscriptionEstablishedCb, nullptr, false, true) == CHIP_NO_ERROR);
+        EXPECT_EQ(Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
+                      &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 20,
+                      onSubscriptionEstablishedCb, nullptr, false, true),
+                  CHIP_NO_ERROR);
     }
 
     // There are too many messages and the test (gcc_debug, which includes many sanity checks) will be quite slow. Note: report
     // engine is using ScheduleWork which cannot be handled by DrainAndServiceIO correctly.
-    ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(60), [&]() {
+    mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(60), [&]() {
         return numSuccessCalls == (app::InteractionModelEngine::kReadHandlerPoolSize + 1) &&
             numSubscriptionEstablishedCalls == (app::InteractionModelEngine::kReadHandlerPoolSize + 1);
     });
 
-    NL_TEST_ASSERT(apSuite, numSuccessCalls == (app::InteractionModelEngine::kReadHandlerPoolSize + 1));
-    NL_TEST_ASSERT(apSuite, numSubscriptionEstablishedCalls == (app::InteractionModelEngine::kReadHandlerPoolSize + 1));
-    NL_TEST_ASSERT(apSuite,
-                   gTestReadInteraction.mNumActiveSubscriptions == (app::InteractionModelEngine::kReadHandlerPoolSize + 1));
+    EXPECT_EQ(numSuccessCalls, (app::InteractionModelEngine::kReadHandlerPoolSize + 1));
+    EXPECT_EQ(numSubscriptionEstablishedCalls, (app::InteractionModelEngine::kReadHandlerPoolSize + 1));
+    EXPECT_EQ(mNumActiveSubscriptions, static_cast<int32_t>(app::InteractionModelEngine::kReadHandlerPoolSize + 1));
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mNumActiveSubscriptions, 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
-    ctx.SetMRPMode(chip::Test::MessagingContext::MRPMode::kDefault);
+    mpContext->SetMRPMode(chip::Test::MessagingContext::MRPMode::kDefault);
     app::InteractionModelEngine::GetInstance()->UnregisterReadHandlerAppCallback();
 }
 
-void TestReadInteraction::TestReadHandler_SubscriptionAppRejection(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_SubscriptionAppRejection)
 {
-    TestContext & ctx                        = *static_cast<TestContext *>(apContext);
-    auto sessionHandle                       = ctx.GetSessionBobToAlice();
+    auto sessionHandle                       = mpContext->GetSessionBobToAlice();
     uint32_t numSuccessCalls                 = 0;
     uint32_t numFailureCalls                 = 0;
     uint32_t numSubscriptionEstablishedCalls = 0;
@@ -1954,46 +1925,45 @@
     // Test the application callback as well to ensure we get the right number of SubscriptionEstablishment/Termination
     // callbacks.
     //
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
 
     //
     // Test the application rejecting subscriptions.
     //
-    gTestReadInteraction.mEmitSubscriptionError = true;
+    mEmitSubscriptionError = true;
 
-    NL_TEST_ASSERT(apSuite,
-                   Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-                       &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 10,
-                       onSubscriptionEstablishedCb, nullptr, false, true) == CHIP_NO_ERROR);
+    EXPECT_EQ(Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
+                  &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 10,
+                  onSubscriptionEstablishedCb, nullptr, false, true),
+              CHIP_NO_ERROR);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, numSuccessCalls == 0);
+    EXPECT_EQ(numSuccessCalls, 0u);
 
     //
     // Failures won't get routed to us here since re-subscriptions are enabled by default in the Controller::SubscribeAttribute
     // implementation.
     //
-    NL_TEST_ASSERT(apSuite, numFailureCalls == 0);
-    NL_TEST_ASSERT(apSuite, numSubscriptionEstablishedCalls == 0);
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 0);
+    EXPECT_EQ(numFailureCalls, 0u);
+    EXPECT_EQ(numSubscriptionEstablishedCalls, 0u);
+    EXPECT_EQ(mNumActiveSubscriptions, 0);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
     app::InteractionModelEngine::GetInstance()->UnregisterReadHandlerAppCallback();
-    gTestReadInteraction.mEmitSubscriptionError = false;
+    mEmitSubscriptionError = false;
 }
 
 #if CHIP_CONFIG_ENABLE_ICD_SERVER != 1
 
 // Subscriber sends the request with particular max-interval value:
 // Max interval equal to client-requested min-interval.
-void TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest1(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_SubscriptionReportingIntervalsTest1)
 {
-    TestContext & ctx                        = *static_cast<TestContext *>(apContext);
-    auto sessionHandle                       = ctx.GetSessionBobToAlice();
+    auto sessionHandle                       = mpContext->GetSessionBobToAlice();
     uint32_t numSuccessCalls                 = 0;
     uint32_t numFailureCalls                 = 0;
     uint32_t numSubscriptionEstablishedCalls = 0;
@@ -2012,16 +1982,16 @@
         numFailureCalls++;
     };
 
-    auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls, &apSuite](const app::ReadClient & readClient,
-                                                                                    chip::SubscriptionId aSubscriptionId) {
+    auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls](const app::ReadClient & readClient,
+                                                                          chip::SubscriptionId aSubscriptionId) {
         uint16_t minInterval = 0, maxInterval = 0;
 
         CHIP_ERROR err = readClient.GetReportingIntervals(minInterval, maxInterval);
 
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        NL_TEST_ASSERT(apSuite, minInterval == 5);
-        NL_TEST_ASSERT(apSuite, maxInterval == 5);
+        EXPECT_EQ(minInterval, 5);
+        EXPECT_EQ(maxInterval, 5);
 
         numSubscriptionEstablishedCalls++;
     };
@@ -2030,46 +2000,45 @@
     // Test the application callback as well to ensure we get the right number of SubscriptionEstablishment/Termination
     // callbacks.
     //
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
 
     //
     // Test the server-side application altering the subscription intervals.
     //
-    gTestReadInteraction.mAlterSubscriptionIntervals = false;
+    mAlterSubscriptionIntervals = false;
 
-    NL_TEST_ASSERT(apSuite,
-                   Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-                       &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 5, 5,
-                       onSubscriptionEstablishedCb, nullptr, true) == CHIP_NO_ERROR);
+    EXPECT_EQ(Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
+                  &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 5, 5,
+                  onSubscriptionEstablishedCb, nullptr, true),
+              CHIP_NO_ERROR);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
     //
     // Failures won't get routed to us here since re-subscriptions are enabled by default in the Controller::SubscribeAttribute
     // implementation.
     //
-    NL_TEST_ASSERT(apSuite, numSuccessCalls != 0);
-    NL_TEST_ASSERT(apSuite, numFailureCalls == 0);
-    NL_TEST_ASSERT(apSuite, numSubscriptionEstablishedCalls == 1);
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 1);
+    EXPECT_NE(numSuccessCalls, 0u);
+    EXPECT_EQ(numFailureCalls, 0u);
+    EXPECT_EQ(numSubscriptionEstablishedCalls, 1u);
+    EXPECT_EQ(mNumActiveSubscriptions, 1);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 0);
+    EXPECT_EQ(mNumActiveSubscriptions, 0);
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
     app::InteractionModelEngine::GetInstance()->UnregisterReadHandlerAppCallback();
-    gTestReadInteraction.mAlterSubscriptionIntervals = false;
+    mAlterSubscriptionIntervals = false;
 }
 
 // Subscriber sends the request with particular max-interval value:
 // Max interval greater than client-requested min-interval but lower than 60m:
 // With no server adjustment.
-void TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest2(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_SubscriptionReportingIntervalsTest2)
 {
-    TestContext & ctx                        = *static_cast<TestContext *>(apContext);
-    auto sessionHandle                       = ctx.GetSessionBobToAlice();
+    auto sessionHandle                       = mpContext->GetSessionBobToAlice();
     uint32_t numSuccessCalls                 = 0;
     uint32_t numFailureCalls                 = 0;
     uint32_t numSubscriptionEstablishedCalls = 0;
@@ -2088,16 +2057,16 @@
         numFailureCalls++;
     };
 
-    auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls, &apSuite](const app::ReadClient & readClient,
-                                                                                    chip::SubscriptionId aSubscriptionId) {
+    auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls](const app::ReadClient & readClient,
+                                                                          chip::SubscriptionId aSubscriptionId) {
         uint16_t minInterval = 0, maxInterval = 0;
 
         CHIP_ERROR err = readClient.GetReportingIntervals(minInterval, maxInterval);
 
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        NL_TEST_ASSERT(apSuite, minInterval == 0);
-        NL_TEST_ASSERT(apSuite, maxInterval == 10);
+        EXPECT_EQ(minInterval, 0);
+        EXPECT_EQ(maxInterval, 10);
 
         numSubscriptionEstablishedCalls++;
     };
@@ -2106,46 +2075,45 @@
     // Test the application callback as well to ensure we get the right number of SubscriptionEstablishment/Termination
     // callbacks.
     //
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
 
     //
     // Test the server-side application altering the subscription intervals.
     //
-    gTestReadInteraction.mAlterSubscriptionIntervals = false;
+    mAlterSubscriptionIntervals = false;
 
-    NL_TEST_ASSERT(apSuite,
-                   Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-                       &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 10,
-                       onSubscriptionEstablishedCb, nullptr, true) == CHIP_NO_ERROR);
+    EXPECT_EQ(Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
+                  &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 10,
+                  onSubscriptionEstablishedCb, nullptr, true),
+              CHIP_NO_ERROR);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
     //
     // Failures won't get routed to us here since re-subscriptions are enabled by default in the Controller::SubscribeAttribute
     // implementation.
     //
-    NL_TEST_ASSERT(apSuite, numSuccessCalls != 0);
-    NL_TEST_ASSERT(apSuite, numFailureCalls == 0);
-    NL_TEST_ASSERT(apSuite, numSubscriptionEstablishedCalls == 1);
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 1);
+    EXPECT_NE(numSuccessCalls, 0u);
+    EXPECT_EQ(numFailureCalls, 0u);
+    EXPECT_EQ(numSubscriptionEstablishedCalls, 1u);
+    EXPECT_EQ(mNumActiveSubscriptions, 1);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 0);
+    EXPECT_EQ(mNumActiveSubscriptions, 0);
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
     app::InteractionModelEngine::GetInstance()->UnregisterReadHandlerAppCallback();
-    gTestReadInteraction.mAlterSubscriptionIntervals = false;
+    mAlterSubscriptionIntervals = false;
 }
 
 // Subscriber sends the request with particular max-interval value:
 // Max interval greater than client-requested min-interval but lower than 60m:
 // With server adjustment to a value greater than client-requested, but less than 60m (allowed).
-void TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest3(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_SubscriptionReportingIntervalsTest3)
 {
-    TestContext & ctx                        = *static_cast<TestContext *>(apContext);
-    auto sessionHandle                       = ctx.GetSessionBobToAlice();
+    auto sessionHandle                       = mpContext->GetSessionBobToAlice();
     uint32_t numSuccessCalls                 = 0;
     uint32_t numFailureCalls                 = 0;
     uint32_t numSubscriptionEstablishedCalls = 0;
@@ -2164,16 +2132,16 @@
         numFailureCalls++;
     };
 
-    auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls, &apSuite](const app::ReadClient & readClient,
-                                                                                    chip::SubscriptionId aSubscriptionId) {
+    auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls](const app::ReadClient & readClient,
+                                                                          chip::SubscriptionId aSubscriptionId) {
         uint16_t minInterval = 0, maxInterval = 0;
 
         CHIP_ERROR err = readClient.GetReportingIntervals(minInterval, maxInterval);
 
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        NL_TEST_ASSERT(apSuite, minInterval == 0);
-        NL_TEST_ASSERT(apSuite, maxInterval == 3000);
+        EXPECT_EQ(minInterval, 0);
+        EXPECT_EQ(maxInterval, 3000);
 
         numSubscriptionEstablishedCalls++;
     };
@@ -2182,37 +2150,37 @@
     // Test the application callback as well to ensure we get the right number of SubscriptionEstablishment/Termination
     // callbacks.
     //
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
 
     //
     // Test the server-side application altering the subscription intervals.
     //
-    gTestReadInteraction.mAlterSubscriptionIntervals = true;
-    gTestReadInteraction.mMaxInterval                = 3000;
-    NL_TEST_ASSERT(apSuite,
-                   Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-                       &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 10,
-                       onSubscriptionEstablishedCb, nullptr, true) == CHIP_NO_ERROR);
+    mAlterSubscriptionIntervals = true;
+    mMaxInterval                = 3000;
+    EXPECT_EQ(Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
+                  &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 10,
+                  onSubscriptionEstablishedCb, nullptr, true),
+              CHIP_NO_ERROR);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
     //
     // Failures won't get routed to us here since re-subscriptions are enabled by default in the Controller::SubscribeAttribute
     // implementation.
     //
-    NL_TEST_ASSERT(apSuite, numSuccessCalls != 0);
-    NL_TEST_ASSERT(apSuite, numFailureCalls == 0);
-    NL_TEST_ASSERT(apSuite, numSubscriptionEstablishedCalls == 1);
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 1);
+    EXPECT_NE(numSuccessCalls, 0u);
+    EXPECT_EQ(numFailureCalls, 0u);
+    EXPECT_EQ(numSubscriptionEstablishedCalls, 1u);
+    EXPECT_EQ(mNumActiveSubscriptions, 1);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 0);
+    EXPECT_EQ(mNumActiveSubscriptions, 0);
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
     app::InteractionModelEngine::GetInstance()->UnregisterReadHandlerAppCallback();
-    gTestReadInteraction.mAlterSubscriptionIntervals = false;
+    mAlterSubscriptionIntervals = false;
 }
 
 #endif // CHIP_CONFIG_ENABLE_ICD_SERVER
@@ -2220,10 +2188,9 @@
 // Subscriber sends the request with particular max-interval value:
 // Max interval greater than client-requested min-interval but lower than 60m:
 // server adjustment to a value greater than client-requested, but greater than 60 (not allowed).
-void TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest4(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_SubscriptionReportingIntervalsTest4)
 {
-    TestContext & ctx                        = *static_cast<TestContext *>(apContext);
-    auto sessionHandle                       = ctx.GetSessionBobToAlice();
+    auto sessionHandle                       = mpContext->GetSessionBobToAlice();
     uint32_t numSuccessCalls                 = 0;
     uint32_t numFailureCalls                 = 0;
     uint32_t numSubscriptionEstablishedCalls = 0;
@@ -2251,36 +2218,36 @@
     // Test the application callback as well to ensure we get the right number of SubscriptionEstablishment/Termination
     // callbacks.
     //
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
 
     //
     // Test the server-side application altering the subscription intervals.
     //
-    gTestReadInteraction.mAlterSubscriptionIntervals = true;
-    gTestReadInteraction.mMaxInterval                = 3700;
-    NL_TEST_ASSERT(apSuite,
-                   Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-                       &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 10,
-                       onSubscriptionEstablishedCb, nullptr, true) == CHIP_NO_ERROR);
+    mAlterSubscriptionIntervals = true;
+    mMaxInterval                = 3700;
+    EXPECT_EQ(Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
+                  &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 10,
+                  onSubscriptionEstablishedCb, nullptr, true),
+              CHIP_NO_ERROR);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
     //
     // Failures won't get routed to us here since re-subscriptions are enabled by default in the Controller::SubscribeAttribute
     // implementation.
     //
-    NL_TEST_ASSERT(apSuite, numSuccessCalls == 0);
-    NL_TEST_ASSERT(apSuite, numSubscriptionEstablishedCalls == 0);
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 0);
+    EXPECT_EQ(numSuccessCalls, 0u);
+    EXPECT_EQ(numSubscriptionEstablishedCalls, 0u);
+    EXPECT_EQ(mNumActiveSubscriptions, 0);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 0);
+    EXPECT_EQ(mNumActiveSubscriptions, 0);
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
     app::InteractionModelEngine::GetInstance()->UnregisterReadHandlerAppCallback();
-    gTestReadInteraction.mAlterSubscriptionIntervals = false;
+    mAlterSubscriptionIntervals = false;
 }
 
 #if CHIP_CONFIG_ENABLE_ICD_SERVER != 1
@@ -2288,10 +2255,9 @@
 // Subscriber sends the request with particular max-interval value:
 // Max interval greater than client-requested min-interval but greater than 60m:
 // With no server adjustment.
-void TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest5(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_SubscriptionReportingIntervalsTest5)
 {
-    TestContext & ctx                        = *static_cast<TestContext *>(apContext);
-    auto sessionHandle                       = ctx.GetSessionBobToAlice();
+    auto sessionHandle                       = mpContext->GetSessionBobToAlice();
     uint32_t numSuccessCalls                 = 0;
     uint32_t numFailureCalls                 = 0;
     uint32_t numSubscriptionEstablishedCalls = 0;
@@ -2310,16 +2276,16 @@
         numFailureCalls++;
     };
 
-    auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls, &apSuite](const app::ReadClient & readClient,
-                                                                                    chip::SubscriptionId aSubscriptionId) {
+    auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls](const app::ReadClient & readClient,
+                                                                          chip::SubscriptionId aSubscriptionId) {
         uint16_t minInterval = 0, maxInterval = 0;
 
         CHIP_ERROR err = readClient.GetReportingIntervals(minInterval, maxInterval);
 
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        NL_TEST_ASSERT(apSuite, minInterval == 0);
-        NL_TEST_ASSERT(apSuite, maxInterval == 4000);
+        EXPECT_EQ(minInterval, 0);
+        EXPECT_EQ(maxInterval, 4000);
 
         numSubscriptionEstablishedCalls++;
     };
@@ -2328,46 +2294,45 @@
     // Test the application callback as well to ensure we get the right number of SubscriptionEstablishment/Termination
     // callbacks.
     //
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
 
     //
     // Test the server-side application altering the subscription intervals.
     //
-    gTestReadInteraction.mAlterSubscriptionIntervals = false;
+    mAlterSubscriptionIntervals = false;
 
-    NL_TEST_ASSERT(apSuite,
-                   Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-                       &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 4000,
-                       onSubscriptionEstablishedCb, nullptr, true) == CHIP_NO_ERROR);
+    EXPECT_EQ(Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
+                  &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 4000,
+                  onSubscriptionEstablishedCb, nullptr, true),
+              CHIP_NO_ERROR);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
     //
     // Failures won't get routed to us here since re-subscriptions are enabled by default in the Controller::SubscribeAttribute
     // implementation.
     //
-    NL_TEST_ASSERT(apSuite, numSuccessCalls != 0);
-    NL_TEST_ASSERT(apSuite, numFailureCalls == 0);
-    NL_TEST_ASSERT(apSuite, numSubscriptionEstablishedCalls == 1);
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 1);
+    EXPECT_NE(numSuccessCalls, 0u);
+    EXPECT_EQ(numFailureCalls, 0u);
+    EXPECT_EQ(numSubscriptionEstablishedCalls, 1u);
+    EXPECT_EQ(mNumActiveSubscriptions, 1);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 0);
+    EXPECT_EQ(mNumActiveSubscriptions, 0);
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
     app::InteractionModelEngine::GetInstance()->UnregisterReadHandlerAppCallback();
-    gTestReadInteraction.mAlterSubscriptionIntervals = false;
+    mAlterSubscriptionIntervals = false;
 }
 
 // Subscriber sends the request with particular max-interval value:
 // Max interval greater than client-requested min-interval but greater than 60m:
 // With server adjustment to a value lower than 60m. Allowed
-void TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest6(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_SubscriptionReportingIntervalsTest6)
 {
-    TestContext & ctx                        = *static_cast<TestContext *>(apContext);
-    auto sessionHandle                       = ctx.GetSessionBobToAlice();
+    auto sessionHandle                       = mpContext->GetSessionBobToAlice();
     uint32_t numSuccessCalls                 = 0;
     uint32_t numFailureCalls                 = 0;
     uint32_t numSubscriptionEstablishedCalls = 0;
@@ -2386,16 +2351,16 @@
         numFailureCalls++;
     };
 
-    auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls, &apSuite](const app::ReadClient & readClient,
-                                                                                    chip::SubscriptionId aSubscriptionId) {
+    auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls](const app::ReadClient & readClient,
+                                                                          chip::SubscriptionId aSubscriptionId) {
         uint16_t minInterval = 0, maxInterval = 0;
 
         CHIP_ERROR err = readClient.GetReportingIntervals(minInterval, maxInterval);
 
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        NL_TEST_ASSERT(apSuite, minInterval == 0);
-        NL_TEST_ASSERT(apSuite, maxInterval == 3000);
+        EXPECT_EQ(minInterval, 0);
+        EXPECT_EQ(maxInterval, 3000);
 
         numSubscriptionEstablishedCalls++;
     };
@@ -2404,46 +2369,45 @@
     // Test the application callback as well to ensure we get the right number of SubscriptionEstablishment/Termination
     // callbacks.
     //
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
 
     //
     // Test the server-side application altering the subscription intervals.
     //
-    gTestReadInteraction.mAlterSubscriptionIntervals = true;
-    gTestReadInteraction.mMaxInterval                = 3000;
-    NL_TEST_ASSERT(apSuite,
-                   Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-                       &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 4000,
-                       onSubscriptionEstablishedCb, nullptr, true) == CHIP_NO_ERROR);
+    mAlterSubscriptionIntervals = true;
+    mMaxInterval                = 3000;
+    EXPECT_EQ(Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
+                  &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 4000,
+                  onSubscriptionEstablishedCb, nullptr, true),
+              CHIP_NO_ERROR);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
     //
     // Failures won't get routed to us here since re-subscriptions are enabled by default in the Controller::SubscribeAttribute
     // implementation.
     //
-    NL_TEST_ASSERT(apSuite, numSuccessCalls != 0);
-    NL_TEST_ASSERT(apSuite, numFailureCalls == 0);
-    NL_TEST_ASSERT(apSuite, numSubscriptionEstablishedCalls == 1);
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 1);
+    EXPECT_NE(numSuccessCalls, 0u);
+    EXPECT_EQ(numFailureCalls, 0u);
+    EXPECT_EQ(numSubscriptionEstablishedCalls, 1u);
+    EXPECT_EQ(mNumActiveSubscriptions, 1);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 0);
+    EXPECT_EQ(mNumActiveSubscriptions, 0);
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
     app::InteractionModelEngine::GetInstance()->UnregisterReadHandlerAppCallback();
-    gTestReadInteraction.mAlterSubscriptionIntervals = false;
+    mAlterSubscriptionIntervals = false;
 }
 
 // Subscriber sends the request with particular max-interval value:
 // Max interval greater than client-requested min-interval but greater than 60m:
 // With server adjustment to a value larger than 60m, but less than max interval. Allowed
-void TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest7(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_SubscriptionReportingIntervalsTest7)
 {
-    TestContext & ctx                        = *static_cast<TestContext *>(apContext);
-    auto sessionHandle                       = ctx.GetSessionBobToAlice();
+    auto sessionHandle                       = mpContext->GetSessionBobToAlice();
     uint32_t numSuccessCalls                 = 0;
     uint32_t numFailureCalls                 = 0;
     uint32_t numSubscriptionEstablishedCalls = 0;
@@ -2462,16 +2426,16 @@
         numFailureCalls++;
     };
 
-    auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls, &apSuite](const app::ReadClient & readClient,
-                                                                                    chip::SubscriptionId aSubscriptionId) {
+    auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls](const app::ReadClient & readClient,
+                                                                          chip::SubscriptionId aSubscriptionId) {
         uint16_t minInterval = 0, maxInterval = 0;
 
         CHIP_ERROR err = readClient.GetReportingIntervals(minInterval, maxInterval);
 
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        NL_TEST_ASSERT(apSuite, minInterval == 0);
-        NL_TEST_ASSERT(apSuite, maxInterval == 3700);
+        EXPECT_EQ(minInterval, 0);
+        EXPECT_EQ(maxInterval, 3700);
 
         numSubscriptionEstablishedCalls++;
     };
@@ -2479,37 +2443,37 @@
     // Test the application callback as well to ensure we get the right number of SubscriptionEstablishment/Termination
     // callbacks.
     //
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
 
     //
     // Test the server-side application altering the subscription intervals.
     //
-    gTestReadInteraction.mAlterSubscriptionIntervals = true;
-    gTestReadInteraction.mMaxInterval                = 3700;
-    NL_TEST_ASSERT(apSuite,
-                   Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-                       &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 4000,
-                       onSubscriptionEstablishedCb, nullptr, true) == CHIP_NO_ERROR);
+    mAlterSubscriptionIntervals = true;
+    mMaxInterval                = 3700;
+    EXPECT_EQ(Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
+                  &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 4000,
+                  onSubscriptionEstablishedCb, nullptr, true),
+              CHIP_NO_ERROR);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
     //
     // Failures won't get routed to us here since re-subscriptions are enabled by default in the Controller::SubscribeAttribute
     // implementation.
     //
-    NL_TEST_ASSERT(apSuite, numSuccessCalls != 0);
-    NL_TEST_ASSERT(apSuite, numFailureCalls == 0);
-    NL_TEST_ASSERT(apSuite, numSubscriptionEstablishedCalls == 1);
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 1);
+    EXPECT_NE(numSuccessCalls, 0u);
+    EXPECT_EQ(numFailureCalls, 0u);
+    EXPECT_EQ(numSubscriptionEstablishedCalls, 1u);
+    EXPECT_EQ(mNumActiveSubscriptions, 1);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 0);
+    EXPECT_EQ(mNumActiveSubscriptions, 0);
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
     app::InteractionModelEngine::GetInstance()->UnregisterReadHandlerAppCallback();
-    gTestReadInteraction.mAlterSubscriptionIntervals = false;
+    mAlterSubscriptionIntervals = false;
 }
 
 #endif // CHIP_CONFIG_ENABLE_ICD_SERVER
@@ -2517,10 +2481,9 @@
 // Subscriber sends the request with particular max-interval value:
 // Max interval greater than client-requested min-interval but greater than 60m:
 // With server adjustment to a value larger than 60m, but larger than max interval. Disallowed
-void TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest8(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_SubscriptionReportingIntervalsTest8)
 {
-    TestContext & ctx                        = *static_cast<TestContext *>(apContext);
-    auto sessionHandle                       = ctx.GetSessionBobToAlice();
+    auto sessionHandle                       = mpContext->GetSessionBobToAlice();
     uint32_t numSuccessCalls                 = 0;
     uint32_t numFailureCalls                 = 0;
     uint32_t numSubscriptionEstablishedCalls = 0;
@@ -2547,44 +2510,43 @@
     // Test the application callback as well to ensure we get the right number of SubscriptionEstablishment/Termination
     // callbacks.
     //
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
 
     //
     // Test the server-side application altering the subscription intervals.
     //
-    gTestReadInteraction.mAlterSubscriptionIntervals = true;
-    gTestReadInteraction.mMaxInterval                = 4100;
-    NL_TEST_ASSERT(apSuite,
-                   Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-                       &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 4000,
-                       onSubscriptionEstablishedCb, nullptr, true) == CHIP_NO_ERROR);
+    mAlterSubscriptionIntervals = true;
+    mMaxInterval                = 4100;
+    EXPECT_EQ(Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
+                  &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 4000,
+                  onSubscriptionEstablishedCb, nullptr, true),
+              CHIP_NO_ERROR);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
     //
     // Failures won't get routed to us here since re-subscriptions are enabled by default in the Controller::SubscribeAttribute
     // implementation.
     //
-    NL_TEST_ASSERT(apSuite, numSuccessCalls == 0);
-    NL_TEST_ASSERT(apSuite, numSubscriptionEstablishedCalls == 0);
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 0);
+    EXPECT_EQ(numSuccessCalls, 0u);
+    EXPECT_EQ(numSubscriptionEstablishedCalls, 0u);
+    EXPECT_EQ(mNumActiveSubscriptions, 0);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 0);
+    EXPECT_EQ(mNumActiveSubscriptions, 0);
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
     app::InteractionModelEngine::GetInstance()->UnregisterReadHandlerAppCallback();
-    gTestReadInteraction.mAlterSubscriptionIntervals = false;
+    mAlterSubscriptionIntervals = false;
 }
 
 // Subscriber sends the request with particular max-interval value:
 // Validate client is not requesting max-interval < min-interval.
-void TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest9(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_SubscriptionReportingIntervalsTest9)
 {
-    TestContext & ctx                        = *static_cast<TestContext *>(apContext);
-    auto sessionHandle                       = ctx.GetSessionBobToAlice();
+    auto sessionHandle                       = mpContext->GetSessionBobToAlice();
     uint32_t numSuccessCalls                 = 0;
     uint32_t numFailureCalls                 = 0;
     uint32_t numSubscriptionEstablishedCalls = 0;
@@ -2612,56 +2574,55 @@
     // Test the application callback as well to ensure we get the right number of SubscriptionEstablishment/Termination
     // callbacks.
     //
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
 
     //
     // Test the server-side application altering the subscription intervals.
     //
-    gTestReadInteraction.mAlterSubscriptionIntervals = false;
+    mAlterSubscriptionIntervals = false;
 
-    NL_TEST_ASSERT(apSuite,
-                   Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-                       &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 5, 4,
-                       onSubscriptionEstablishedCb, nullptr, true) == CHIP_ERROR_INVALID_ARGUMENT);
+    EXPECT_EQ(Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
+                  &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 5, 4,
+                  onSubscriptionEstablishedCb, nullptr, true),
+              CHIP_ERROR_INVALID_ARGUMENT);
 
     //
     // Failures won't get routed to us here since re-subscriptions are enabled by default in the Controller::SubscribeAttribute
     // implementation.
     //
-    NL_TEST_ASSERT(apSuite, numSuccessCalls == 0);
-    NL_TEST_ASSERT(apSuite, numSubscriptionEstablishedCalls == 0);
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 0);
+    EXPECT_EQ(numSuccessCalls, 0u);
+    EXPECT_EQ(numSubscriptionEstablishedCalls, 0u);
+    EXPECT_EQ(mNumActiveSubscriptions, 0);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 
-    NL_TEST_ASSERT(apSuite, gTestReadInteraction.mNumActiveSubscriptions == 0);
+    EXPECT_EQ(mNumActiveSubscriptions, 0);
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
     app::InteractionModelEngine::GetInstance()->UnregisterReadHandlerAppCallback();
-    gTestReadInteraction.mAlterSubscriptionIntervals = false;
+    mAlterSubscriptionIntervals = false;
 }
 
 /**
  * When the liveness timeout of a subscription to ICD is reached, the subscription will enter "InactiveICDSubscription" state, the
  * client should call "OnActiveModeNotification" to re-activate it again when the check-in message is received from the ICD.
  */
-void TestReadInteraction::TestSubscribe_OnActiveModeNotification(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestSubscribe_OnActiveModeNotification)
 {
-    TestContext & ctx  = *static_cast<TestContext *>(apContext);
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
-    ctx.SetMRPMode(chip::Test::MessagingContext::MRPMode::kResponsive);
+    mpContext->SetMRPMode(chip::Test::MessagingContext::MRPMode::kResponsive);
 
     {
         TestResubscriptionCallback callback;
-        app::ReadClient readClient(app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(), callback,
+        app::ReadClient readClient(app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(), callback,
                                    app::ReadClient::InteractionType::Subscribe);
 
         callback.mScheduleLITResubscribeImmediately = false;
         callback.SetReadClient(&readClient);
 
-        app::ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice());
+        app::ReadPrepareParams readPrepareParams(mpContext->GetSessionBobToAlice());
 
         // Read full wildcard paths, repeat twice to ensure chunking.
         app::AttributePathParams attributePathParams[1];
@@ -2677,16 +2638,16 @@
         readPrepareParams.mIsPeerLIT                 = true;
 
         auto err = readClient.SendAutoResubscribeRequest(std::move(readPrepareParams));
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
         //
         // Drive servicing IO till we have established a subscription.
         //
-        ctx.GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
-                                        [&]() { return callback.mOnSubscriptionEstablishedCount >= 1; });
-        NL_TEST_ASSERT(apSuite, callback.mOnSubscriptionEstablishedCount == 1);
-        NL_TEST_ASSERT(apSuite, callback.mOnError == 0);
-        NL_TEST_ASSERT(apSuite, callback.mOnResubscriptionsAttempted == 0);
+        mpContext->GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
+                                               [&]() { return callback.mOnSubscriptionEstablishedCount >= 1; });
+        EXPECT_EQ(callback.mOnSubscriptionEstablishedCount, 1);
+        EXPECT_EQ(callback.mOnError, 0);
+        EXPECT_EQ(callback.mOnResubscriptionsAttempted, 0);
         chip::app::ReadHandler * readHandler = app::InteractionModelEngine::GetInstance()->ActiveHandlerAt(0);
 
         uint16_t minInterval;
@@ -2699,52 +2660,52 @@
         // WakeUp() is called.
         //
         //
-        ctx.GetLoopback().mNumMessagesToDrop = chip::Test::LoopbackTransport::kUnlimitedMessageCount;
-        ctx.GetIOContext().DriveIOUntil(ComputeSubscriptionTimeout(System::Clock::Seconds16(maxInterval)), [&]() { return false; });
-        NL_TEST_ASSERT(apSuite, callback.mOnResubscriptionsAttempted == 1);
-        NL_TEST_ASSERT(apSuite, callback.mLastError == CHIP_ERROR_LIT_SUBSCRIBE_INACTIVE_TIMEOUT);
+        mpContext->GetLoopback().mNumMessagesToDrop = chip::Test::LoopbackTransport::kUnlimitedMessageCount;
+        mpContext->GetIOContext().DriveIOUntil(ComputeSubscriptionTimeout(System::Clock::Seconds16(maxInterval)),
+                                               [&]() { return false; });
+        EXPECT_EQ(callback.mOnResubscriptionsAttempted, 1);
+        EXPECT_EQ(callback.mLastError, CHIP_ERROR_LIT_SUBSCRIBE_INACTIVE_TIMEOUT);
 
-        ctx.GetLoopback().mNumMessagesToDrop = 0;
+        mpContext->GetLoopback().mNumMessagesToDrop = 0;
         callback.ClearCounters();
         app::InteractionModelEngine::GetInstance()->OnActiveModeNotification(
             ScopedNodeId(readClient.GetPeerNodeId(), readClient.GetFabricIndex()));
-        NL_TEST_ASSERT(apSuite, callback.mOnResubscriptionsAttempted == 1);
-        NL_TEST_ASSERT(apSuite, callback.mLastError == CHIP_ERROR_TIMEOUT);
+        EXPECT_EQ(callback.mOnResubscriptionsAttempted, 1);
+        EXPECT_EQ(callback.mLastError, CHIP_ERROR_TIMEOUT);
 
         //
         // Drive servicing IO till we have established a subscription.
         //
-        ctx.GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
-                                        [&]() { return callback.mOnSubscriptionEstablishedCount == 1; });
-        NL_TEST_ASSERT(apSuite, callback.mOnSubscriptionEstablishedCount == 1);
+        mpContext->GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
+                                               [&]() { return callback.mOnSubscriptionEstablishedCount == 1; });
+        EXPECT_EQ(callback.mOnSubscriptionEstablishedCount, 1);
 
         //
         // With re-sub enabled, we shouldn't have encountered any errors
         //
-        NL_TEST_ASSERT(apSuite, callback.mOnError == 0);
-        NL_TEST_ASSERT(apSuite, callback.mOnDone == 0);
+        EXPECT_EQ(callback.mOnError, 0);
+        EXPECT_EQ(callback.mOnDone, 0);
     }
 
-    ctx.SetMRPMode(chip::Test::MessagingContext::MRPMode::kDefault);
+    mpContext->SetMRPMode(chip::Test::MessagingContext::MRPMode::kDefault);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
 /**
  * When the liveness timeout of a subscription to ICD is reached, the subscription will enter "InactiveICDSubscription" state, the
  * client should call "OnActiveModeNotification" to re-activate it again when the check-in message is received from the ICD.
  */
-void TestReadInteraction::TestSubscribe_DynamicLITSubscription(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestSubscribe_DynamicLITSubscription)
 {
-    TestContext & ctx  = *static_cast<TestContext *>(apContext);
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
-    ctx.SetMRPMode(chip::Test::MessagingContext::MRPMode::kResponsive);
+    mpContext->SetMRPMode(chip::Test::MessagingContext::MRPMode::kResponsive);
 
     {
         TestResubscriptionCallback callback;
-        app::ReadClient readClient(app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(), callback,
+        app::ReadClient readClient(app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(), callback,
                                    app::ReadClient::InteractionType::Subscribe);
 
         responseDirective                           = kSendDataResponse;
@@ -2752,7 +2713,7 @@
         callback.SetReadClient(&readClient);
         isLitIcd = false;
 
-        app::ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice());
+        app::ReadPrepareParams readPrepareParams(mpContext->GetSessionBobToAlice());
 
         // Read full wildcard paths, repeat twice to ensure chunking.
         app::AttributePathParams attributePathParams[1];
@@ -2768,16 +2729,16 @@
         readPrepareParams.mIsPeerLIT                 = true;
 
         auto err = readClient.SendAutoResubscribeRequest(std::move(readPrepareParams));
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
         //
         // Drive servicing IO till we have established a subscription.
         //
-        ctx.GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
-                                        [&]() { return callback.mOnSubscriptionEstablishedCount >= 1; });
-        NL_TEST_ASSERT(apSuite, callback.mOnSubscriptionEstablishedCount == 1);
-        NL_TEST_ASSERT(apSuite, callback.mOnError == 0);
-        NL_TEST_ASSERT(apSuite, callback.mOnResubscriptionsAttempted == 0);
+        mpContext->GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
+                                               [&]() { return callback.mOnSubscriptionEstablishedCount >= 1; });
+        EXPECT_EQ(callback.mOnSubscriptionEstablishedCount, 1);
+        EXPECT_EQ(callback.mOnError, 0);
+        EXPECT_EQ(callback.mOnResubscriptionsAttempted, 0);
         chip::app::ReadHandler * readHandler = app::InteractionModelEngine::GetInstance()->ActiveHandlerAt(0);
 
         uint16_t minInterval;
@@ -2793,27 +2754,27 @@
         //
         // Even if we set the peer type to LIT before, the report indicates that the peer is a SIT now, it will just bahve as
         // normal, non-LIT subscriptions.
-        ctx.GetLoopback().mNumMessagesToDrop = chip::Test::LoopbackTransport::kUnlimitedMessageCount;
-        ctx.GetIOContext().DriveIOUntil(ComputeSubscriptionTimeout(System::Clock::Seconds16(maxInterval)),
-                                        [&]() { return callback.mOnResubscriptionsAttempted != 0; });
-        NL_TEST_ASSERT(apSuite, callback.mOnResubscriptionsAttempted == 1);
-        NL_TEST_ASSERT(apSuite, callback.mLastError == CHIP_ERROR_TIMEOUT);
+        mpContext->GetLoopback().mNumMessagesToDrop = chip::Test::LoopbackTransport::kUnlimitedMessageCount;
+        mpContext->GetIOContext().DriveIOUntil(ComputeSubscriptionTimeout(System::Clock::Seconds16(maxInterval)),
+                                               [&]() { return callback.mOnResubscriptionsAttempted != 0; });
+        EXPECT_EQ(callback.mOnResubscriptionsAttempted, 1);
+        EXPECT_EQ(callback.mLastError, CHIP_ERROR_TIMEOUT);
 
-        ctx.GetLoopback().mNumMessagesToDrop = 0;
+        mpContext->GetLoopback().mNumMessagesToDrop = 0;
         callback.ClearCounters();
 
         //
         // Drive servicing IO till we have established a subscription.
         //
-        ctx.GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
-                                        [&]() { return callback.mOnSubscriptionEstablishedCount == 1; });
-        NL_TEST_ASSERT(apSuite, callback.mOnSubscriptionEstablishedCount == 1);
+        mpContext->GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
+                                               [&]() { return callback.mOnSubscriptionEstablishedCount == 1; });
+        EXPECT_EQ(callback.mOnSubscriptionEstablishedCount, 1);
 
         //
         // With re-sub enabled, we shouldn't have encountered any errors
         //
-        NL_TEST_ASSERT(apSuite, callback.mOnError == 0);
-        NL_TEST_ASSERT(apSuite, callback.mOnDone == 0);
+        EXPECT_EQ(callback.mOnError, 0);
+        EXPECT_EQ(callback.mOnDone, 0);
 
         // Part 2. SIT -> LIT
 
@@ -2826,24 +2787,25 @@
             app::InteractionModelEngine::GetInstance()->GetReportingEngine().SetDirty(path);
         }
         callback.ClearCounters();
-        ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(60), [&]() {
+        mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(60), [&]() {
             return app::InteractionModelEngine::GetInstance()->GetNumDirtySubscriptions() == 0;
         });
 
         // When we received the update that OperatingMode becomes LIT, we automatically set the inner peer type to LIT ICD.
-        ctx.GetLoopback().mNumMessagesToDrop = chip::Test::LoopbackTransport::kUnlimitedMessageCount;
-        ctx.GetIOContext().DriveIOUntil(ComputeSubscriptionTimeout(System::Clock::Seconds16(maxInterval)), [&]() { return false; });
-        NL_TEST_ASSERT(apSuite, callback.mOnResubscriptionsAttempted == 1);
-        NL_TEST_ASSERT(apSuite, callback.mLastError == CHIP_ERROR_LIT_SUBSCRIBE_INACTIVE_TIMEOUT);
+        mpContext->GetLoopback().mNumMessagesToDrop = chip::Test::LoopbackTransport::kUnlimitedMessageCount;
+        mpContext->GetIOContext().DriveIOUntil(ComputeSubscriptionTimeout(System::Clock::Seconds16(maxInterval)),
+                                               [&]() { return false; });
+        EXPECT_EQ(callback.mOnResubscriptionsAttempted, 1);
+        EXPECT_EQ(callback.mLastError, CHIP_ERROR_LIT_SUBSCRIBE_INACTIVE_TIMEOUT);
 
-        ctx.GetLoopback().mNumMessagesToDrop = 0;
+        mpContext->GetLoopback().mNumMessagesToDrop = 0;
         callback.ClearCounters();
     }
 
-    ctx.SetMRPMode(chip::Test::MessagingContext::MRPMode::kDefault);
+    mpContext->SetMRPMode(chip::Test::MessagingContext::MRPMode::kDefault);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
     isLitIcd = false;
 }
@@ -2852,22 +2814,21 @@
  * When the liveness timeout of a subscription to ICD is reached, the app can issue resubscription immediately
  * if they know the peer is active.
  */
-void TestReadInteraction::TestSubscribe_ImmediatelyResubscriptionForLIT(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestSubscribe_ImmediatelyResubscriptionForLIT)
 {
-    TestContext & ctx  = *static_cast<TestContext *>(apContext);
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
-    ctx.SetMRPMode(chip::Test::MessagingContext::MRPMode::kResponsive);
+    mpContext->SetMRPMode(chip::Test::MessagingContext::MRPMode::kResponsive);
 
     {
         TestResubscriptionCallback callback;
-        app::ReadClient readClient(app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(), callback,
+        app::ReadClient readClient(app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(), callback,
                                    app::ReadClient::InteractionType::Subscribe);
 
         callback.mScheduleLITResubscribeImmediately = true;
         callback.SetReadClient(&readClient);
 
-        app::ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice());
+        app::ReadPrepareParams readPrepareParams(mpContext->GetSessionBobToAlice());
 
         // Read full wildcard paths, repeat twice to ensure chunking.
         app::AttributePathParams attributePathParams[1];
@@ -2883,16 +2844,16 @@
         readPrepareParams.mIsPeerLIT                 = true;
 
         auto err = readClient.SendAutoResubscribeRequest(std::move(readPrepareParams));
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
         //
         // Drive servicing IO till we have established a subscription.
         //
-        ctx.GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
-                                        [&]() { return callback.mOnSubscriptionEstablishedCount >= 1; });
-        NL_TEST_ASSERT(apSuite, callback.mOnSubscriptionEstablishedCount == 1);
-        NL_TEST_ASSERT(apSuite, callback.mOnError == 0);
-        NL_TEST_ASSERT(apSuite, callback.mOnResubscriptionsAttempted == 0);
+        mpContext->GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
+                                               [&]() { return callback.mOnSubscriptionEstablishedCount >= 1; });
+        EXPECT_EQ(callback.mOnSubscriptionEstablishedCount, 1);
+        EXPECT_EQ(callback.mOnError, 0);
+        EXPECT_EQ(callback.mOnResubscriptionsAttempted, 0);
         chip::app::ReadHandler * readHandler = app::InteractionModelEngine::GetInstance()->ActiveHandlerAt(0);
 
         uint16_t minInterval;
@@ -2905,83 +2866,76 @@
         // WakeUp() is called.
         //
         //
-        ctx.GetLoopback().mNumMessagesToDrop = chip::Test::LoopbackTransport::kUnlimitedMessageCount;
-        ctx.GetIOContext().DriveIOUntil(ComputeSubscriptionTimeout(System::Clock::Seconds16(maxInterval)),
-                                        [&]() { return callback.mLastError == CHIP_ERROR_LIT_SUBSCRIBE_INACTIVE_TIMEOUT; });
-        NL_TEST_ASSERT(apSuite, callback.mOnResubscriptionsAttempted == 1);
-        NL_TEST_ASSERT(apSuite, callback.mLastError == CHIP_ERROR_LIT_SUBSCRIBE_INACTIVE_TIMEOUT);
+        mpContext->GetLoopback().mNumMessagesToDrop = chip::Test::LoopbackTransport::kUnlimitedMessageCount;
+        mpContext->GetIOContext().DriveIOUntil(ComputeSubscriptionTimeout(System::Clock::Seconds16(maxInterval)),
+                                               [&]() { return callback.mLastError == CHIP_ERROR_LIT_SUBSCRIBE_INACTIVE_TIMEOUT; });
+        EXPECT_EQ(callback.mOnResubscriptionsAttempted, 1);
+        EXPECT_EQ(callback.mLastError, CHIP_ERROR_LIT_SUBSCRIBE_INACTIVE_TIMEOUT);
 
-        ctx.GetLoopback().mNumMessagesToDrop = 0;
+        mpContext->GetLoopback().mNumMessagesToDrop = 0;
         callback.ClearCounters();
 
         //
         // Drive servicing IO till we have established a subscription.
         //
-        ctx.GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
-                                        [&]() { return callback.mOnSubscriptionEstablishedCount == 1; });
-        NL_TEST_ASSERT(apSuite, callback.mOnSubscriptionEstablishedCount == 1);
+        mpContext->GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
+                                               [&]() { return callback.mOnSubscriptionEstablishedCount == 1; });
+        EXPECT_EQ(callback.mOnSubscriptionEstablishedCount, 1);
 
         //
         // With re-sub enabled, we shouldn't have encountered any errors
         //
-        NL_TEST_ASSERT(apSuite, callback.mOnError == 0);
-        NL_TEST_ASSERT(apSuite, callback.mOnDone == 0);
+        EXPECT_EQ(callback.mOnError, 0);
+        EXPECT_EQ(callback.mOnDone, 0);
     }
 
-    ctx.SetMRPMode(chip::Test::MessagingContext::MRPMode::kDefault);
+    mpContext->SetMRPMode(chip::Test::MessagingContext::MRPMode::kDefault);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestReadInteraction::TestReadHandler_MultipleReads(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_MultipleReads)
 {
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
-
     static_assert(CHIP_IM_MAX_REPORTS_IN_FLIGHT <= app::InteractionModelEngine::kReadHandlerPoolSize,
                   "How can we have more reports in flight than read handlers?");
 
-    MultipleReadHelper(apSuite, ctx, CHIP_IM_MAX_REPORTS_IN_FLIGHT);
+    MultipleReadHelper(mpContext, CHIP_IM_MAX_REPORTS_IN_FLIGHT);
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 }
 
-void TestReadInteraction::TestReadHandler_OneSubscribeMultipleReads(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_OneSubscribeMultipleReads)
 {
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
-
     static_assert(CHIP_IM_MAX_REPORTS_IN_FLIGHT <= app::InteractionModelEngine::kReadHandlerPoolSize,
                   "How can we have more reports in flight than read handlers?");
     static_assert(CHIP_IM_MAX_REPORTS_IN_FLIGHT > 1, "We won't do any reads");
 
-    SubscribeThenReadHelper(apSuite, ctx, 1, CHIP_IM_MAX_REPORTS_IN_FLIGHT - 1);
+    SubscribeThenReadHelper(mpContext, 1, CHIP_IM_MAX_REPORTS_IN_FLIGHT - 1);
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 }
 
-void TestReadInteraction::TestReadHandler_TwoSubscribesMultipleReads(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_TwoSubscribesMultipleReads)
 {
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
-
     static_assert(CHIP_IM_MAX_REPORTS_IN_FLIGHT <= app::InteractionModelEngine::kReadHandlerPoolSize,
                   "How can we have more reports in flight than read handlers?");
     static_assert(CHIP_IM_MAX_REPORTS_IN_FLIGHT > 2, "We won't do any reads");
 
-    SubscribeThenReadHelper(apSuite, ctx, 2, CHIP_IM_MAX_REPORTS_IN_FLIGHT - 2);
+    SubscribeThenReadHelper(mpContext, 2, CHIP_IM_MAX_REPORTS_IN_FLIGHT - 2);
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 }
 
-void TestReadInteraction::SubscribeThenReadHelper(nlTestSuite * apSuite, TestContext & aCtx, size_t aSubscribeCount,
-                                                  size_t aReadCount)
+void TestRead::SubscribeThenReadHelper(TestContext * apCtx, size_t aSubscribeCount, size_t aReadCount)
 {
-    auto sessionHandle                       = aCtx.GetSessionBobToAlice();
+    auto sessionHandle                       = apCtx->GetSessionBobToAlice();
     uint32_t numSuccessCalls                 = 0;
     uint32_t numSubscriptionEstablishedCalls = 0;
 
@@ -2998,90 +2952,89 @@
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onFailureCb = [&apSuite](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) {
+    auto onFailureCb = [](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) {
         //
         // We shouldn't be encountering any failures in this test.
         //
-        NL_TEST_ASSERT(apSuite, false);
+        EXPECT_TRUE(false);
     };
 
-    auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls, &apSuite, &aCtx, aSubscribeCount, aReadCount,
-                                        &numReadSuccessCalls, &numReadFailureCalls](const app::ReadClient & readClient,
-                                                                                    chip::SubscriptionId aSubscriptionId) {
+    auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls, &apCtx, aSubscribeCount, aReadCount, &numReadSuccessCalls,
+                                        &numReadFailureCalls](const app::ReadClient & readClient,
+                                                              chip::SubscriptionId aSubscriptionId) {
         numSubscriptionEstablishedCalls++;
         if (numSubscriptionEstablishedCalls == aSubscribeCount)
         {
-            MultipleReadHelperInternal(apSuite, aCtx, aReadCount, numReadSuccessCalls, numReadFailureCalls);
+            MultipleReadHelperInternal(apCtx, aReadCount, numReadSuccessCalls, numReadFailureCalls);
         }
     };
 
     for (size_t i = 0; i < aSubscribeCount; ++i)
     {
-        NL_TEST_ASSERT(apSuite,
-                       Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-                           &aCtx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 10,
-                           onSubscriptionEstablishedCb, nullptr, false, true) == CHIP_NO_ERROR);
+        EXPECT_EQ(Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
+                      &apCtx->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 10,
+                      onSubscriptionEstablishedCb, nullptr, false, true),
+                  CHIP_NO_ERROR);
     }
 
-    aCtx.DrainAndServiceIO();
+    apCtx->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, numSuccessCalls == aSubscribeCount);
-    NL_TEST_ASSERT(apSuite, numSubscriptionEstablishedCalls == aSubscribeCount);
-    NL_TEST_ASSERT(apSuite, numReadSuccessCalls == aReadCount);
-    NL_TEST_ASSERT(apSuite, numReadFailureCalls == 0);
+    EXPECT_EQ(numSuccessCalls, aSubscribeCount);
+    EXPECT_EQ(numSubscriptionEstablishedCalls, aSubscribeCount);
+    EXPECT_EQ(numReadSuccessCalls, aReadCount);
+    EXPECT_EQ(numReadFailureCalls, 0u);
 }
 
 // The guts of MultipleReadHelper which take references to the success/failure
 // counts to modify and assume the consumer will be spinning the event loop.
-void TestReadInteraction::MultipleReadHelperInternal(nlTestSuite * apSuite, TestContext & aCtx, size_t aReadCount,
-                                                     uint32_t & aNumSuccessCalls, uint32_t & aNumFailureCalls)
+void TestRead::MultipleReadHelperInternal(TestContext * apCtx, size_t aReadCount, uint32_t & aNumSuccessCalls,
+                                          uint32_t & aNumFailureCalls)
 {
-    NL_TEST_ASSERT(apSuite, aNumSuccessCalls == 0);
-    NL_TEST_ASSERT(apSuite, aNumFailureCalls == 0);
+    EXPECT_EQ(aNumSuccessCalls, 0u);
+    EXPECT_EQ(aNumFailureCalls, 0u);
 
-    auto sessionHandle = aCtx.GetSessionBobToAlice();
+    auto sessionHandle = apCtx->GetSessionBobToAlice();
 
     responseDirective = kSendDataResponse;
 
     uint16_t firstExpectedResponse = totalReadCount + 1;
 
-    auto onFailureCb = [apSuite, &aNumFailureCalls](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) {
+    auto onFailureCb = [&aNumFailureCalls](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) {
         aNumFailureCalls++;
 
-        NL_TEST_ASSERT(apSuite, attributePath == nullptr);
+        EXPECT_EQ(attributePath, nullptr);
     };
 
     for (size_t i = 0; i < aReadCount; ++i)
     {
-        auto onSuccessCb = [&aNumSuccessCalls, apSuite, firstExpectedResponse,
-                            i](const app::ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
-            NL_TEST_ASSERT(apSuite, dataResponse == firstExpectedResponse + i);
+        auto onSuccessCb = [&aNumSuccessCalls, firstExpectedResponse, i](const app::ConcreteDataAttributePath & attributePath,
+                                                                         const auto & dataResponse) {
+            EXPECT_EQ(dataResponse, firstExpectedResponse + i);
             aNumSuccessCalls++;
         };
 
-        NL_TEST_ASSERT(apSuite,
-                       Controller::ReadAttribute<Clusters::UnitTesting::Attributes::Int16u::TypeInfo>(
-                           &aCtx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb) == CHIP_NO_ERROR);
+        EXPECT_EQ(Controller::ReadAttribute<Clusters::UnitTesting::Attributes::Int16u::TypeInfo>(
+                      &apCtx->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb),
+                  CHIP_NO_ERROR);
     }
 }
 
-void TestReadInteraction::MultipleReadHelper(nlTestSuite * apSuite, TestContext & aCtx, size_t aReadCount)
+void TestRead::MultipleReadHelper(TestContext * apCtx, size_t aReadCount)
 {
     uint32_t numSuccessCalls = 0;
     uint32_t numFailureCalls = 0;
 
-    MultipleReadHelperInternal(apSuite, aCtx, aReadCount, numSuccessCalls, numFailureCalls);
+    MultipleReadHelperInternal(apCtx, aReadCount, numSuccessCalls, numFailureCalls);
 
-    aCtx.DrainAndServiceIO();
+    apCtx->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, numSuccessCalls == aReadCount);
-    NL_TEST_ASSERT(apSuite, numFailureCalls == 0);
+    EXPECT_EQ(numSuccessCalls, aReadCount);
+    EXPECT_EQ(numFailureCalls, 0u);
 }
 
-void TestReadInteraction::TestReadHandler_MultipleSubscriptionsWithDataVersionFilter(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_MultipleSubscriptionsWithDataVersionFilter)
 {
-    TestContext & ctx                        = *static_cast<TestContext *>(apContext);
-    auto sessionHandle                       = ctx.GetSessionBobToAlice();
+    auto sessionHandle                       = mpContext->GetSessionBobToAlice();
     uint32_t numSuccessCalls                 = 0;
     uint32_t numSubscriptionEstablishedCalls = 0;
 
@@ -3089,19 +3042,18 @@
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onSuccessCb = [apSuite, &numSuccessCalls](const app::ConcreteDataAttributePath & attributePath,
-                                                   const auto & dataResponse) {
-        NL_TEST_ASSERT(apSuite, attributePath.mDataVersion.HasValue() && attributePath.mDataVersion.Value() == kDataVersion);
+    auto onSuccessCb = [&numSuccessCalls](const app::ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
+        EXPECT_TRUE(attributePath.mDataVersion.HasValue() && attributePath.mDataVersion.Value() == kDataVersion);
         numSuccessCalls++;
     };
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onFailureCb = [&apSuite](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) {
+    auto onFailureCb = [](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) {
         //
         // We shouldn't be encountering any failures in this test.
         //
-        NL_TEST_ASSERT(apSuite, false);
+        EXPECT_TRUE(false);
     };
 
     auto onSubscriptionEstablishedCb = [&numSubscriptionEstablishedCalls](const app::ReadClient & readClient,
@@ -3117,15 +3069,15 @@
     chip::Optional<chip::DataVersion> dataVersion(1);
     for (size_t i = 0; i < (app::InteractionModelEngine::kReadHandlerPoolSize + 1); i++)
     {
-        NL_TEST_ASSERT(apSuite,
-                       Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-                           &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 10,
-                           onSubscriptionEstablishedCb, nullptr, false, true, dataVersion) == CHIP_NO_ERROR);
+        EXPECT_EQ(Controller::SubscribeAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
+                      &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, 0, 10,
+                      onSubscriptionEstablishedCb, nullptr, false, true, dataVersion),
+                  CHIP_NO_ERROR);
     }
 
     // There are too many messages and the test (gcc_debug, which includes many sanity checks) will be quite slow. Note: report
     // engine is using ScheduleWork which cannot be handled by DrainAndServiceIO correctly.
-    ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(30), [&]() {
+    mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(30), [&]() {
         return numSubscriptionEstablishedCalls == (app::InteractionModelEngine::kReadHandlerPoolSize + 1) &&
             numSuccessCalls == (app::InteractionModelEngine::kReadHandlerPoolSize + 1);
     });
@@ -3134,17 +3086,16 @@
                  numSuccessCalls, uint32_t(app::InteractionModelEngine::kReadHandlerPoolSize + 1), numSubscriptionEstablishedCalls,
                  uint32_t(app::InteractionModelEngine::kReadHandlerPoolSize + 1));
 
-    NL_TEST_ASSERT(apSuite, numSuccessCalls == (app::InteractionModelEngine::kReadHandlerPoolSize + 1));
-    NL_TEST_ASSERT(apSuite, numSubscriptionEstablishedCalls == (app::InteractionModelEngine::kReadHandlerPoolSize + 1));
+    EXPECT_EQ(numSuccessCalls, (app::InteractionModelEngine::kReadHandlerPoolSize + 1));
+    EXPECT_EQ(numSubscriptionEstablishedCalls, (app::InteractionModelEngine::kReadHandlerPoolSize + 1));
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestReadInteraction::TestReadHandlerResourceExhaustion_MultipleReads(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandlerResourceExhaustion_MultipleReads)
 {
-    TestContext & ctx        = *static_cast<TestContext *>(apContext);
-    auto sessionHandle       = ctx.GetSessionBobToAlice();
+    auto sessionHandle       = mpContext->GetSessionBobToAlice();
     uint32_t numSuccessCalls = 0;
     uint32_t numFailureCalls = 0;
 
@@ -3158,33 +3109,33 @@
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onFailureCb = [&apSuite, &numFailureCalls](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) {
+    auto onFailureCb = [&numFailureCalls](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) {
         numFailureCalls++;
 
-        NL_TEST_ASSERT(apSuite, aError == CHIP_IM_GLOBAL_STATUS(Busy));
-        NL_TEST_ASSERT(apSuite, attributePath == nullptr);
+        EXPECT_EQ(aError, CHIP_IM_GLOBAL_STATUS(Busy));
+        EXPECT_EQ(attributePath, nullptr);
     };
 
     app::InteractionModelEngine::GetInstance()->SetHandlerCapacityForReads(0);
     app::InteractionModelEngine::GetInstance()->SetForceHandlerQuota(true);
 
-    NL_TEST_ASSERT(apSuite,
-                   Controller::ReadAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
-                       &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb) == CHIP_NO_ERROR);
+    EXPECT_EQ(Controller::ReadAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
+                  &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb),
+              CHIP_NO_ERROR);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
     app::InteractionModelEngine::GetInstance()->SetHandlerCapacityForReads(-1);
     app::InteractionModelEngine::GetInstance()->SetForceHandlerQuota(false);
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
 
-    NL_TEST_ASSERT(apSuite, numSuccessCalls == 0);
-    NL_TEST_ASSERT(apSuite, numFailureCalls == 1);
+    EXPECT_EQ(numSuccessCalls, 0u);
+    EXPECT_EQ(numFailureCalls, 1u);
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestReadInteraction::TestReadFabricScopedWithoutFabricFilter(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadFabricScopedWithoutFabricFilter)
 {
     /**
      *  TODO: we cannot implement the e2e read tests w/ fabric filter since the test session has only one session, and the
@@ -3196,20 +3147,18 @@
      * encoder.
      *   - When a fabric filtered read request is received, the response encoder is able to encode the attribute correctly.
      */
-    TestContext & ctx       = *static_cast<TestContext *>(apContext);
-    auto sessionHandle      = ctx.GetSessionBobToAlice();
+    auto sessionHandle      = mpContext->GetSessionBobToAlice();
     bool onSuccessCbInvoked = false, onFailureCbInvoked = false;
 
     responseDirective = kSendDataResponse;
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onSuccessCb = [apSuite, &onSuccessCbInvoked](const app::ConcreteDataAttributePath & attributePath,
-                                                      const auto & dataResponse) {
+    auto onSuccessCb = [&onSuccessCbInvoked](const app::ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
         size_t len = 0;
 
-        NL_TEST_ASSERT(apSuite, dataResponse.ComputeSize(&len) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, len > 1);
+        EXPECT_EQ(dataResponse.ComputeSize(&len), CHIP_NO_ERROR);
+        EXPECT_GT(len, 1u);
 
         onSuccessCbInvoked = true;
     };
@@ -3221,17 +3170,17 @@
     };
 
     Controller::ReadAttribute<Clusters::UnitTesting::Attributes::ListFabricScoped::TypeInfo>(
-        &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, false /* fabric filtered */);
+        &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, false /* fabric filtered */);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, onSuccessCbInvoked && !onFailureCbInvoked);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients() == 0);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(onSuccessCbInvoked && !onFailureCbInvoked);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients(), 0u);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestReadInteraction::TestReadFabricScopedWithFabricFilter(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadFabricScopedWithFabricFilter)
 {
     /**
      *  TODO: we cannot implement the e2e read tests w/ fabric filter since the test session has only one session, and the
@@ -3243,20 +3192,18 @@
      * encoder.
      *   - When a fabric filtered read request is received, the response encoder is able to encode the attribute correctly.
      */
-    TestContext & ctx       = *static_cast<TestContext *>(apContext);
-    auto sessionHandle      = ctx.GetSessionBobToAlice();
+    auto sessionHandle      = mpContext->GetSessionBobToAlice();
     bool onSuccessCbInvoked = false, onFailureCbInvoked = false;
 
     responseDirective = kSendDataResponse;
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onSuccessCb = [apSuite, &onSuccessCbInvoked](const app::ConcreteDataAttributePath & attributePath,
-                                                      const auto & dataResponse) {
+    auto onSuccessCb = [&onSuccessCbInvoked](const app::ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
         size_t len = 0;
 
-        NL_TEST_ASSERT(apSuite, dataResponse.ComputeSize(&len) == CHIP_NO_ERROR);
-        NL_TEST_ASSERT(apSuite, len == 1);
+        EXPECT_EQ(dataResponse.ComputeSize(&len), CHIP_NO_ERROR);
+        EXPECT_EQ(len, 1u);
 
         // TODO: Uncomment the following code after we have fabric support in unit tests.
         /*
@@ -3264,7 +3211,7 @@
         if (iter.Next())
         {
             auto & item = iter.GetValue();
-            NL_TEST_ASSERT(apSuite, item.fabricIndex == 1);
+            EXPECT_EQ(item.fabricIndex, 1);
         }
         */
         onSuccessCbInvoked = true;
@@ -3277,14 +3224,14 @@
     };
 
     Controller::ReadAttribute<Clusters::UnitTesting::Attributes::ListFabricScoped::TypeInfo>(
-        &ctx.GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, true /* fabric filtered */);
+        &mpContext->GetExchangeManager(), sessionHandle, kTestEndpointId, onSuccessCb, onFailureCb, true /* fabric filtered */);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, onSuccessCbInvoked && !onFailureCbInvoked);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients() == 0);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(onSuccessCbInvoked && !onFailureCbInvoked);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients(), 0u);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
 namespace SubscriptionPathQuotaHelpers {
@@ -3356,7 +3303,7 @@
     int32_t reportsReceived = 0;
 };
 
-void EstablishReadOrSubscriptions(nlTestSuite * apSuite, const SessionHandle & sessionHandle, size_t numSubs, size_t pathPerSub,
+void EstablishReadOrSubscriptions(const SessionHandle & sessionHandle, size_t numSubs, size_t pathPerSub,
                                   app::AttributePathParams path, app::ReadClient::InteractionType type,
                                   app::ReadClient::Callback * callback, std::vector<std::unique_ptr<app::ReadClient>> & readClients)
 {
@@ -3376,26 +3323,25 @@
         std::unique_ptr<app::ReadClient> readClient =
             std::make_unique<app::ReadClient>(app::InteractionModelEngine::GetInstance(),
                                               app::InteractionModelEngine::GetInstance()->GetExchangeManager(), *callback, type);
-        NL_TEST_ASSERT(apSuite, readClient->SendRequest(readParams) == CHIP_NO_ERROR);
+        EXPECT_EQ(readClient->SendRequest(readParams), CHIP_NO_ERROR);
         readClients.push_back(std::move(readClient));
     }
 }
 
 } // namespace SubscriptionPathQuotaHelpers
 
-void TestReadInteraction::TestSubscribeAttributeDeniedNotExistPath(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestSubscribeAttributeDeniedNotExistPath)
 {
-    TestContext & ctx  = *static_cast<TestContext *>(apContext);
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
-    ctx.SetMRPMode(chip::Test::MessagingContext::MRPMode::kResponsive);
+    mpContext->SetMRPMode(chip::Test::MessagingContext::MRPMode::kResponsive);
 
     {
         SubscriptionPathQuotaHelpers::TestReadCallback callback;
-        app::ReadClient readClient(app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(), callback,
+        app::ReadClient readClient(app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(), callback,
                                    app::ReadClient::InteractionType::Subscribe);
 
-        app::ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice());
+        app::ReadPrepareParams readPrepareParams(mpContext->GetSessionBobToAlice());
 
         app::AttributePathParams attributePathParams[1];
         readPrepareParams.mpAttributePathParamsList    = attributePathParams;
@@ -3409,33 +3355,32 @@
         readPrepareParams.mMaxIntervalCeilingSeconds = 1;
 
         auto err = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
+        mpContext->DrainAndServiceIO();
 
-        NL_TEST_ASSERT(apSuite, callback.mOnError == 1);
-        NL_TEST_ASSERT(apSuite, callback.mLastError == CHIP_IM_GLOBAL_STATUS(InvalidAction));
-        NL_TEST_ASSERT(apSuite, callback.mOnDone == 1);
+        EXPECT_EQ(callback.mOnError, 1u);
+        EXPECT_EQ(callback.mLastError, CHIP_IM_GLOBAL_STATUS(InvalidAction));
+        EXPECT_EQ(callback.mOnDone, 1u);
     }
 
-    ctx.SetMRPMode(chip::Test::MessagingContext::MRPMode::kDefault);
+    mpContext->SetMRPMode(chip::Test::MessagingContext::MRPMode::kDefault);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestReadInteraction::TestReadHandler_KillOverQuotaSubscriptions(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_KillOverQuotaSubscriptions)
 {
-    // Note: We cannot use ctx.DrainAndServiceIO() since the perpetual read will make DrainAndServiceIO never return.
+    // Note: We cannot use mpContext->DrainAndServiceIO() since the perpetual read will make DrainAndServiceIO never return.
     using namespace SubscriptionPathQuotaHelpers;
-    TestContext & ctx  = *static_cast<TestContext *>(apContext);
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
     const auto kExpectedParallelSubs =
-        app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric * ctx.GetFabricTable().FabricCount();
+        app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric * mpContext->GetFabricTable().FabricCount();
     const auto kExpectedParallelPaths = kExpectedParallelSubs * app::InteractionModelEngine::kMinSupportedPathsPerSubscription;
 
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
 
     // Here, we set up two background perpetual read requests to simulate parallel Read + Subscriptions.
     // We don't care about the data read, we only care about the existence of such read transactions.
@@ -3444,19 +3389,17 @@
     TestPerpetualListReadCallback perpetualReadCallback;
     std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-    EstablishReadOrSubscriptions(apSuite, ctx.GetSessionAliceToBob(), 1, 1,
+    EstablishReadOrSubscriptions(mpContext->GetSessionAliceToBob(), 1, 1,
                                  app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, kPerpetualAttributeid),
                                  app::ReadClient::InteractionType::Read, &perpetualReadCallback, readClients);
-    EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1, 1,
+    EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1, 1,
                                  app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, kPerpetualAttributeid),
                                  app::ReadClient::InteractionType::Read, &perpetualReadCallback, readClients);
-    ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+    mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
         return app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read) == 2;
     });
     // Ensure our read transactions are established.
-    NL_TEST_ASSERT(apSuite,
-                   app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read) ==
-                       2);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read), 2u);
 
     // Intentially establish subscriptions using exceeded resources.
     app::InteractionModelEngine::GetInstance()->SetForceHandlerQuota(false);
@@ -3468,29 +3411,28 @@
     //
     // Subscription A
     EstablishReadOrSubscriptions(
-        apSuite, ctx.GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerSubscription + 1,
+        mpContext->GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerSubscription + 1,
         app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
         app::ReadClient::InteractionType::Subscribe, &readCallback, readClients);
     // Subscription B
     EstablishReadOrSubscriptions(
-        apSuite, ctx.GetSessionBobToAlice(), kExpectedParallelSubs, app::InteractionModelEngine::kMinSupportedPathsPerSubscription,
+        mpContext->GetSessionBobToAlice(), kExpectedParallelSubs, app::InteractionModelEngine::kMinSupportedPathsPerSubscription,
         app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
         app::ReadClient::InteractionType::Subscribe, &readCallback, readClients);
 
     // There are too many messages and the test (gcc_debug, which includes many sanity checks) will be quite slow. Note: report
     // engine is using ScheduleWork which cannot be handled by DrainAndServiceIO correctly.
-    ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+    mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
         return readCallback.mOnSubscriptionEstablishedCount == kExpectedParallelSubs + 1 &&
             readCallback.mAttributeCount ==
             kExpectedParallelSubs * app::InteractionModelEngine::kMinSupportedPathsPerSubscription +
                 app::InteractionModelEngine::kMinSupportedPathsPerSubscription + 1;
     });
 
-    NL_TEST_ASSERT(apSuite,
-                   readCallback.mAttributeCount ==
-                       kExpectedParallelSubs * app::InteractionModelEngine::kMinSupportedPathsPerSubscription +
-                           app::InteractionModelEngine::kMinSupportedPathsPerSubscription + 1);
-    NL_TEST_ASSERT(apSuite, readCallback.mOnSubscriptionEstablishedCount == kExpectedParallelSubs + 1);
+    EXPECT_EQ(readCallback.mAttributeCount,
+              kExpectedParallelSubs * app::InteractionModelEngine::kMinSupportedPathsPerSubscription +
+                  app::InteractionModelEngine::kMinSupportedPathsPerSubscription + 1);
+    EXPECT_EQ(readCallback.mOnSubscriptionEstablishedCount, kExpectedParallelSubs + 1);
 
     // We have set up the environment for testing the evicting logic.
     // We now have a full stable of subscriptions setup AND we've artificially limited the capacity, creation of further
@@ -3506,28 +3448,28 @@
         TestReadCallback callback;
         std::vector<std::unique_ptr<app::ReadClient>> outReadClient;
         EstablishReadOrSubscriptions(
-            apSuite, ctx.GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerSubscription + 1,
+            mpContext->GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerSubscription + 1,
             app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
             app::ReadClient::InteractionType::Subscribe, &callback, outReadClient);
 
-        ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return callback.mOnError == 1; });
+        mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return callback.mOnError == 1; });
 
         // Over-sized request after used all paths will receive Paths Exhausted status code.
-        NL_TEST_ASSERT(apSuite, callback.mOnError == 1);
-        NL_TEST_ASSERT(apSuite, callback.mLastError == CHIP_IM_GLOBAL_STATUS(PathsExhausted));
+        EXPECT_EQ(callback.mOnError, 1u);
+        EXPECT_EQ(callback.mLastError, CHIP_IM_GLOBAL_STATUS(PathsExhausted));
     }
 
     // This next test validates that a compliant subscription request will kick out an existing subscription (arguably, the one that
     // was previously established with more paths than the limit per fabric)
     {
         EstablishReadOrSubscriptions(
-            apSuite, ctx.GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerSubscription,
+            mpContext->GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerSubscription,
             app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
             app::ReadClient::InteractionType::Subscribe, &readCallback, readClients);
 
         readCallback.ClearCounters();
         // Run until the new subscription got setup fully as viewed by the client.
-        ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+        mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
             return readCallback.mOnSubscriptionEstablishedCount == 1 &&
                 readCallback.mAttributeCount == app::InteractionModelEngine::kMinSupportedPathsPerSubscription;
         });
@@ -3535,8 +3477,8 @@
         // This read handler should evict some existing subscriptions for enough space.
         // Validate that the new subscription got setup fully as viewed by the client. And we will validate we handled this
         // subscription by evicting the correct subscriptions later.
-        NL_TEST_ASSERT(apSuite, readCallback.mOnSubscriptionEstablishedCount == 1);
-        NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == app::InteractionModelEngine::kMinSupportedPathsPerSubscription);
+        EXPECT_EQ(readCallback.mOnSubscriptionEstablishedCount, 1u);
+        EXPECT_EQ(readCallback.mAttributeCount, app::InteractionModelEngine::kMinSupportedPathsPerSubscription);
     }
 
     // Validate we evicted the right subscription for handling the new subscription above.
@@ -3552,8 +3494,9 @@
     readCallback.ClearCounters();
 
     // Run until all subscriptions are clean.
-    ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(60),
-                                    [&]() { return app::InteractionModelEngine::GetInstance()->GetNumDirtySubscriptions() == 0; });
+    mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(60), [&]() {
+        return app::InteractionModelEngine::GetInstance()->GetNumDirtySubscriptions() == 0;
+    });
 
     // Before the above subscription, we have one subscription with kMinSupportedPathsPerSubscription + 1 paths, we should evict
     // that subscription before evicting any other subscriptions, which will result we used exactly kExpectedParallelPaths and have
@@ -3561,28 +3504,26 @@
     // We have exactly one subscription than uses more resources than others, so the interaction model must evict it first, and we
     // will have exactly kExpectedParallelPaths only when that subscription have been evicted. We use this indirect method to verify
     // the subscriptions since the read client won't shutdown until the timeout fired.
-    NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == kExpectedParallelPaths);
-    NL_TEST_ASSERT(apSuite,
-                   app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                       app::ReadHandler::InteractionType::Subscribe) == static_cast<uint32_t>(kExpectedParallelSubs));
+    EXPECT_EQ(readCallback.mAttributeCount, kExpectedParallelPaths);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Subscribe),
+              static_cast<uint32_t>(kExpectedParallelSubs));
 
     // Part 2: Testing per fabric minimas.
     // Validate we have more than kMinSupportedSubscriptionsPerFabric subscriptions for testing per fabric minimas.
-    NL_TEST_ASSERT(apSuite,
-                   app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                       app::ReadHandler::InteractionType::Subscribe, ctx.GetAliceFabricIndex()) >
-                       app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric);
+    EXPECT_GT(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Subscribe,
+                                                                                   mpContext->GetAliceFabricIndex()),
+              app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric);
 
     // The following check will trigger the logic in im to kill the read handlers that use more paths than the limit per fabric.
     {
         EstablishReadOrSubscriptions(
-            apSuite, ctx.GetSessionAliceToBob(), app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric,
+            mpContext->GetSessionAliceToBob(), app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric,
             app::InteractionModelEngine::kMinSupportedPathsPerSubscription,
             app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
             app::ReadClient::InteractionType::Subscribe, &readCallbackFabric2, readClients);
 
         // Run until we have established the subscriptions.
-        ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+        mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
             return readCallbackFabric2.mOnSubscriptionEstablishedCount ==
                 app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric &&
                 readCallbackFabric2.mAttributeCount ==
@@ -3591,13 +3532,11 @@
         });
 
         // Verify the subscriptions are established successfully. We will check if we evicted the expected subscriptions later.
-        NL_TEST_ASSERT(apSuite,
-                       readCallbackFabric2.mOnSubscriptionEstablishedCount ==
-                           app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric);
-        NL_TEST_ASSERT(apSuite,
-                       readCallbackFabric2.mAttributeCount ==
-                           app::InteractionModelEngine::kMinSupportedPathsPerSubscription *
-                               app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric);
+        EXPECT_EQ(readCallbackFabric2.mOnSubscriptionEstablishedCount,
+                  app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric);
+        EXPECT_EQ(readCallbackFabric2.mAttributeCount,
+                  app::InteractionModelEngine::kMinSupportedPathsPerSubscription *
+                      app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric);
     }
 
     // Validate the subscriptions are handled by evicting one or more subscriptions from Fabric A.
@@ -3612,55 +3551,49 @@
     readCallbackFabric2.ClearCounters();
 
     // Run until all subscriptions are clean.
-    ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(60),
-                                    [&]() { return app::InteractionModelEngine::GetInstance()->GetNumDirtySubscriptions() == 0; });
+    mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(60), [&]() {
+        return app::InteractionModelEngine::GetInstance()->GetNumDirtySubscriptions() == 0;
+    });
 
     // Some subscriptions on fabric 1 should be evicted since fabric 1 is using more resources than the limits.
-    NL_TEST_ASSERT(apSuite,
-                   readCallback.mAttributeCount ==
-                       app::InteractionModelEngine::kMinSupportedPathsPerSubscription *
-                           app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric);
-    NL_TEST_ASSERT(apSuite,
-                   readCallbackFabric2.mAttributeCount ==
-                       app::InteractionModelEngine::kMinSupportedPathsPerSubscription *
-                           app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric);
-    NL_TEST_ASSERT(apSuite,
-                   app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                       app::ReadHandler::InteractionType::Subscribe, ctx.GetAliceFabricIndex()) ==
-                       app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric);
-    NL_TEST_ASSERT(apSuite,
-                   app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                       app::ReadHandler::InteractionType::Subscribe, ctx.GetBobFabricIndex()) ==
-                       app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric);
+    EXPECT_EQ(readCallback.mAttributeCount,
+              app::InteractionModelEngine::kMinSupportedPathsPerSubscription *
+                  app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric);
+    EXPECT_EQ(readCallbackFabric2.mAttributeCount,
+              app::InteractionModelEngine::kMinSupportedPathsPerSubscription *
+                  app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Subscribe,
+                                                                                   mpContext->GetAliceFabricIndex()),
+              app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Subscribe,
+                                                                                   mpContext->GetBobFabricIndex()),
+              app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric);
 
     // Ensure our read transactions are still alive.
-    NL_TEST_ASSERT(apSuite,
-                   app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read) ==
-                       2);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read), 2u);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
     // Shutdown all clients
     readClients.clear();
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
     app::InteractionModelEngine::GetInstance()->SetForceHandlerQuota(false);
     app::InteractionModelEngine::GetInstance()->SetHandlerCapacityForSubscriptions(-1);
     app::InteractionModelEngine::GetInstance()->SetPathPoolCapacityForSubscriptions(-1);
 }
 
-void TestReadInteraction::TestReadHandler_KillOldestSubscriptions(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_KillOldestSubscriptions)
 {
     using namespace SubscriptionPathQuotaHelpers;
-    TestContext & ctx  = *static_cast<TestContext *>(apContext);
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
     const auto kExpectedParallelSubs =
-        app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric * ctx.GetFabricTable().FabricCount();
+        app::InteractionModelEngine::kMinSupportedSubscriptionsPerFabric * mpContext->GetFabricTable().FabricCount();
     const auto kExpectedParallelPaths = kExpectedParallelSubs * app::InteractionModelEngine::kMinSupportedPathsPerSubscription;
 
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
 
     TestReadCallback readCallback;
     std::vector<std::unique_ptr<app::ReadClient>> readClients;
@@ -3671,50 +3604,47 @@
 
     // This should just use all availbale resources.
     EstablishReadOrSubscriptions(
-        apSuite, ctx.GetSessionBobToAlice(), kExpectedParallelSubs, app::InteractionModelEngine::kMinSupportedPathsPerSubscription,
+        mpContext->GetSessionBobToAlice(), kExpectedParallelSubs, app::InteractionModelEngine::kMinSupportedPathsPerSubscription,
         app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
         app::ReadClient::InteractionType::Subscribe, &readCallback, readClients);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite,
-                   readCallback.mAttributeCount ==
-                       kExpectedParallelSubs * app::InteractionModelEngine::kMinSupportedPathsPerSubscription);
-    NL_TEST_ASSERT(apSuite, readCallback.mOnSubscriptionEstablishedCount == kExpectedParallelSubs);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == kExpectedParallelSubs);
+    EXPECT_EQ(readCallback.mAttributeCount, kExpectedParallelSubs * app::InteractionModelEngine::kMinSupportedPathsPerSubscription);
+    EXPECT_EQ(readCallback.mOnSubscriptionEstablishedCount, kExpectedParallelSubs);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), kExpectedParallelSubs);
 
     // The following check will trigger the logic in im to kill the read handlers that uses more paths than the limit per fabric.
     {
         TestReadCallback callback;
         std::vector<std::unique_ptr<app::ReadClient>> outReadClient;
         EstablishReadOrSubscriptions(
-            apSuite, ctx.GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerSubscription + 1,
+            mpContext->GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerSubscription + 1,
             app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
             app::ReadClient::InteractionType::Subscribe, &callback, outReadClient);
 
-        ctx.DrainAndServiceIO();
+        mpContext->DrainAndServiceIO();
 
         // Over-sized request after used all paths will receive Paths Exhausted status code.
-        NL_TEST_ASSERT(apSuite, callback.mOnError == 1);
-        NL_TEST_ASSERT(apSuite, callback.mLastError == CHIP_IM_GLOBAL_STATUS(PathsExhausted));
+        EXPECT_EQ(callback.mOnError, 1u);
+        EXPECT_EQ(callback.mLastError, CHIP_IM_GLOBAL_STATUS(PathsExhausted));
     }
 
     // The following check will trigger the logic in im to kill the read handlers that uses more paths than the limit per fabric.
     {
         EstablishReadOrSubscriptions(
-            apSuite, ctx.GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerSubscription,
+            mpContext->GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerSubscription,
             app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
             app::ReadClient::InteractionType::Subscribe, &readCallback, readClients);
         readCallback.ClearCounters();
 
-        ctx.DrainAndServiceIO();
+        mpContext->DrainAndServiceIO();
 
         // This read handler should evict some existing subscriptions for enough space
-        NL_TEST_ASSERT(apSuite, readCallback.mOnSubscriptionEstablishedCount == 1);
-        NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == app::InteractionModelEngine::kMinSupportedPathsPerSubscription);
-        NL_TEST_ASSERT(apSuite,
-                       app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() ==
-                           static_cast<size_t>(kExpectedParallelSubs));
+        EXPECT_EQ(readCallback.mOnSubscriptionEstablishedCount, 1u);
+        EXPECT_EQ(readCallback.mAttributeCount, app::InteractionModelEngine::kMinSupportedPathsPerSubscription);
+        EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(),
+                  static_cast<size_t>(kExpectedParallelSubs));
     }
 
     {
@@ -3725,17 +3655,17 @@
         app::InteractionModelEngine::GetInstance()->GetReportingEngine().SetDirty(path);
     }
     readCallback.ClearCounters();
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount <= kExpectedParallelPaths);
+    EXPECT_LE(readCallback.mAttributeCount, kExpectedParallelPaths);
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
     // Shutdown all clients
     readClients.clear();
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
     app::InteractionModelEngine::GetInstance()->SetForceHandlerQuota(false);
     app::InteractionModelEngine::GetInstance()->SetHandlerCapacityForSubscriptions(-1);
     app::InteractionModelEngine::GetInstance()->SetPathPoolCapacityForSubscriptions(-1);
@@ -3748,12 +3678,10 @@
     int MaxFabrics          = -1;
 };
 
-static void TestReadHandler_ParallelReads_TestCase(nlTestSuite * apSuite, void * apContext,
+static void TestReadHandler_ParallelReads_TestCase(TestContext * apContext,
                                                    const TestReadHandler_ParallelReads_TestCase_Parameters & params,
                                                    std::function<void()> body)
 {
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
-
     app::InteractionModelEngine::GetInstance()->SetForceHandlerQuota(true);
     app::InteractionModelEngine::GetInstance()->SetHandlerCapacityForReads(params.ReadHandlerCapacity);
     app::InteractionModelEngine::GetInstance()->SetConfigMaxFabrics(params.MaxFabrics);
@@ -3763,10 +3691,10 @@
 
     // Clean up
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
-    ctx.DrainAndServiceIO();
+    apContext->DrainAndServiceIO();
 
     // Sanity check
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(apContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 
     app::InteractionModelEngine::GetInstance()->SetForceHandlerQuota(false);
     app::InteractionModelEngine::GetInstance()->SetHandlerCapacityForReads(-1);
@@ -3774,22 +3702,20 @@
     app::InteractionModelEngine::GetInstance()->SetPathPoolCapacityForReads(-1);
 }
 
-void TestReadInteraction::TestReadHandler_ParallelReads(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_ParallelReads)
 {
-    // Note: We cannot use ctx.DrainAndServiceIO() except at the end of each test case since the perpetual read transactions will
-    // never end.
-    // Note: We use ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { CONDITION }); and NL_TEST_ASSERT(apSuite,
-    // CONDITION ) to ensure the CONDITION is satisfied.
+    // Note: We cannot use mpContext->DrainAndServiceIO() except at the end of each test case since the perpetual read transactions
+    // will never end. Note: We use mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { CONDITION }); and
+    // EXPECT_EQ( CONDITION ) to ensure the CONDITION is satisfied.
     using namespace SubscriptionPathQuotaHelpers;
     using Params = TestReadHandler_ParallelReads_TestCase_Parameters;
 
-    TestContext & ctx  = *static_cast<TestContext *>(apContext);
-    auto sessionHandle = ctx.GetSessionBobToAlice();
+    auto sessionHandle = mpContext->GetSessionBobToAlice();
 
-    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction);
+    app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(this);
 
     auto TestCase = [&](const TestReadHandler_ParallelReads_TestCase_Parameters & params, std::function<void()> body) {
-        TestReadHandler_ParallelReads_TestCase(apSuite, apContext, params, body);
+        TestReadHandler_ParallelReads_TestCase(mpContext, params, body);
     };
 
     // Case 1.1: 2 reads used up the path pool (but not the ReadHandler pool), and one incoming oversized read request =>
@@ -3806,35 +3732,35 @@
             TestPerpetualListReadCallback backgroundReadCallback2;
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback1, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback2, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0;
             });
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
 
             backgroundReadCallback1.ClearCounter();
             backgroundReadCallback2.ClearCounter();
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1,
+                mpContext->GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The two subscriptions should still alive
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
             // The new read request should be rejected
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError != 0);
-            NL_TEST_ASSERT(apSuite, readCallback.mLastError == CHIP_IM_GLOBAL_STATUS(PathsExhausted));
+            EXPECT_NE(readCallback.mOnError, 0u);
+            EXPECT_EQ(readCallback.mLastError, CHIP_IM_GLOBAL_STATUS(PathsExhausted));
         });
 
     // Case 1.2: 2 reads used up the ReadHandler pool (not the PathPool), and one incoming oversized read request => Busy.
@@ -3851,33 +3777,33 @@
             TestPerpetualListReadCallback backgroundReadCallback2;
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback1, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback2, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0;
             });
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
 
             backgroundReadCallback1.ClearCounter();
             backgroundReadCallback2.ClearCounter();
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1,
+                mpContext->GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The two subscriptions should still alive
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
             // The new read request should be rejected
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError != 0);
-            NL_TEST_ASSERT(apSuite, readCallback.mLastError == CHIP_IM_GLOBAL_STATUS(Busy));
+            EXPECT_NE(readCallback.mOnError, 0u);
+            EXPECT_EQ(readCallback.mLastError, CHIP_IM_GLOBAL_STATUS(Busy));
         });
 
     // Case 1.3.1: If we have enough resource, any read requests will be accepted (case for oversized read request).
@@ -3893,39 +3819,38 @@
             TestPerpetualListReadCallback backgroundReadCallback2;
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback1, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionAliceToBob(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionAliceToBob(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback2, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0;
             });
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1,
+                mpContext->GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be accepted
-            NL_TEST_ASSERT(apSuite,
-                           readCallback.mAttributeCount == app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1);
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError == 0);
+            EXPECT_EQ(readCallback.mAttributeCount, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1);
+            EXPECT_EQ(readCallback.mOnError, 0u);
 
             // The two subscriptions should still alive
             backgroundReadCallback1.ClearCounter();
             backgroundReadCallback2.ClearCounter();
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0;
             });
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
         });
 
     // Case 1.3.2: If we have enough resource, any read requests will be accepted (case for non-oversized read requests)
@@ -3941,41 +3866,41 @@
             TestPerpetualListReadCallback backgroundReadCallback2;
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback1, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionAliceToBob(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionAliceToBob(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback2, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0;
             });
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
 
             backgroundReadCallback1.ClearCounter();
             backgroundReadCallback2.ClearCounter();
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionAliceToBob(), 1, 1,
+                mpContext->GetSessionAliceToBob(), 1, 1,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be accepted
-            NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == 1);
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError == 0);
+            EXPECT_EQ(readCallback.mAttributeCount, 1u);
+            EXPECT_EQ(readCallback.mOnError, 0u);
 
             // The two subscriptions should still alive
             backgroundReadCallback1.ClearCounter();
             backgroundReadCallback2.ClearCounter();
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0;
             });
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
         });
 
     // Case 2: 1 oversized read and one non-oversized read, and one incoming read request from __another__ fabric => accept by
@@ -3992,46 +3917,46 @@
             TestPerpetualListReadCallback backgroundReadCallback;
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &readCallbackForOversizedRead, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
-                                            [&]() { return readCallbackForOversizedRead.reportsReceived > 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
+                                                   [&]() { return readCallbackForOversizedRead.reportsReceived > 0; });
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
-                                            [&]() { return backgroundReadCallback.reportsReceived > 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
+                                                   [&]() { return backgroundReadCallback.reportsReceived > 0; });
 
-            NL_TEST_ASSERT(apSuite, readCallbackForOversizedRead.reportsReceived > 0 && backgroundReadCallback.reportsReceived > 0);
+            EXPECT_TRUE(readCallbackForOversizedRead.reportsReceived > 0 && backgroundReadCallback.reportsReceived > 0);
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
+                mpContext->GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be accepted.
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError == 0);
-            NL_TEST_ASSERT(apSuite, readCallback.mOnDone == 1);
-            NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
+            EXPECT_EQ(readCallback.mOnError, 0u);
+            EXPECT_EQ(readCallback.mOnDone, 1u);
+            EXPECT_EQ(readCallback.mAttributeCount, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
 
             // The oversized read handler should be evicted -> We should have one active read handler.
-            NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == 1);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), 1u);
 
             backgroundReadCallback.ClearCounter();
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
-                                            [&]() { return backgroundReadCallback.reportsReceived > 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
+                                                   [&]() { return backgroundReadCallback.reportsReceived > 0; });
 
             // We don't check the readCallbackForOversizedRead, since it cannot prove anything -- it can be 0 even when the
             // oversized read request is alive. We ensure this by checking (1) we have only one active read handler, (2) the one
             // active read handler is the non-oversized one.
 
             // The non-oversized read handler should not be evicted.
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback.reportsReceived > 0);
+            EXPECT_GT(backgroundReadCallback.reportsReceived, 0);
         });
 
     // Case 2 (Repeat): we swapped the order of the oversized and non-oversized read handler to ensure we always evict the oversized
@@ -4048,46 +3973,46 @@
             TestPerpetualListReadCallback backgroundReadCallback;
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
-                                            [&]() { return backgroundReadCallback.reportsReceived > 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
+                                                   [&]() { return backgroundReadCallback.reportsReceived > 0; });
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &readCallbackForOversizedRead, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
-                                            [&]() { return readCallbackForOversizedRead.reportsReceived > 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
+                                                   [&]() { return readCallbackForOversizedRead.reportsReceived > 0; });
 
-            NL_TEST_ASSERT(apSuite, readCallbackForOversizedRead.reportsReceived > 0 && backgroundReadCallback.reportsReceived > 0);
+            EXPECT_TRUE(readCallbackForOversizedRead.reportsReceived > 0 && backgroundReadCallback.reportsReceived > 0);
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
+                mpContext->GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be accepted.
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError == 0);
-            NL_TEST_ASSERT(apSuite, readCallback.mOnDone == 1);
-            NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
+            EXPECT_EQ(readCallback.mOnError, 0u);
+            EXPECT_EQ(readCallback.mOnDone, 1u);
+            EXPECT_EQ(readCallback.mAttributeCount, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
 
             // The oversized read handler should be evicted -> We should have one active read handler.
-            NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == 1);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), 1u);
 
             backgroundReadCallback.ClearCounter();
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
-                                            [&]() { return backgroundReadCallback.reportsReceived > 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
+                                                   [&]() { return backgroundReadCallback.reportsReceived > 0; });
 
             // We don't check the readCallbackForOversizedRead, since it cannot prove anything -- it can be 0 even when the
             // oversized read request is alive. We ensure this by checking (1) we have only one active read handler, (2) the one
             // active read handler is the non-oversized one.
 
             // The non-oversized read handler should not be evicted.
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback.reportsReceived > 0);
+            EXPECT_GT(backgroundReadCallback.reportsReceived, 0);
         });
 
     // Case 3: one oversized read and one non-oversized read, the remaining path in PathPool is suffcient but the ReadHandler pool
@@ -4106,37 +4031,37 @@
             TestPerpetualListReadCallback backgroundReadCallback;
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &readCallbackForOversizedRead, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return backgroundReadCallback.reportsReceived > 0 && readCallbackForOversizedRead.reportsReceived > 0;
             });
 
-            NL_TEST_ASSERT(apSuite, readCallbackForOversizedRead.reportsReceived > 0 && backgroundReadCallback.reportsReceived > 0);
+            EXPECT_TRUE(readCallbackForOversizedRead.reportsReceived > 0 && backgroundReadCallback.reportsReceived > 0);
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
+                mpContext->GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be rejected.
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError != 0);
-            NL_TEST_ASSERT(apSuite, readCallback.mLastError == CHIP_IM_GLOBAL_STATUS(Busy));
+            EXPECT_NE(readCallback.mOnError, 0u);
+            EXPECT_EQ(readCallback.mLastError, CHIP_IM_GLOBAL_STATUS(Busy));
 
             // Ensure the two read transactions are not evicted.
             backgroundReadCallback.ClearCounter();
             readCallbackForOversizedRead.ClearCounter();
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return readCallbackForOversizedRead.reportsReceived > 0 && backgroundReadCallback.reportsReceived > 0;
             });
-            NL_TEST_ASSERT(apSuite, readCallbackForOversizedRead.reportsReceived > 0 && backgroundReadCallback.reportsReceived > 0);
+            EXPECT_TRUE(readCallbackForOversizedRead.reportsReceived > 0 && backgroundReadCallback.reportsReceived > 0);
         });
 
     // Case 4.1: 1 fabric is oversized, and one incoming read request from __another__ fabric => accept by evicting one read request
@@ -4154,43 +4079,43 @@
             TestPerpetualListReadCallback backgroundReadCallback2;
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback1, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
-                                            [&]() { return backgroundReadCallback1.reportsReceived > 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
+                                                   [&]() { return backgroundReadCallback1.reportsReceived > 0; });
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback2, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
-                                            [&]() { return backgroundReadCallback2.reportsReceived > 0; });
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
+                                                   [&]() { return backgroundReadCallback2.reportsReceived > 0; });
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
 
             backgroundReadCallback1.ClearCounter();
             backgroundReadCallback2.ClearCounter();
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
+                mpContext->GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be rejected.
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError == 0);
-            NL_TEST_ASSERT(apSuite, readCallback.mOnDone == 1);
-            NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
+            EXPECT_EQ(readCallback.mOnError, 0u);
+            EXPECT_EQ(readCallback.mOnDone, 1u);
+            EXPECT_EQ(readCallback.mAttributeCount, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
 
             // One of the read requests from Bob to Alice should be evicted.
             // We should have only one 1 active read handler, since the transaction from Alice to Bob has finished already, and one
             // of two Bob to Alice transactions has been evicted.
-            NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == 1);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), 1u);
 
             // Note: Younger read handler will be evicted.
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
-                                            [&]() { return backgroundReadCallback1.reportsReceived > 0; });
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback1.reportsReceived > 0);
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
+                                                   [&]() { return backgroundReadCallback1.reportsReceived > 0; });
+            EXPECT_GT(backgroundReadCallback1.reportsReceived, 0);
         });
 
     // Case 4.2: Like case 4.1, but now the over sized fabric contains one (older) oversized read request and one (younger)
@@ -4207,44 +4132,44 @@
             TestPerpetualListReadCallback backgroundReadCallback2;
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback1, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
-                                            [&]() { return backgroundReadCallback1.reportsReceived > 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
+                                                   [&]() { return backgroundReadCallback1.reportsReceived > 0; });
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback2, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
-                                            [&]() { return backgroundReadCallback2.reportsReceived > 0; });
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
+                                                   [&]() { return backgroundReadCallback2.reportsReceived > 0; });
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
 
             backgroundReadCallback1.ClearCounter();
             backgroundReadCallback2.ClearCounter();
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
+                mpContext->GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be rejected.
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError == 0);
-            NL_TEST_ASSERT(apSuite, readCallback.mOnDone == 1);
-            NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
+            EXPECT_EQ(readCallback.mOnError, 0u);
+            EXPECT_EQ(readCallback.mOnDone, 1u);
+            EXPECT_EQ(readCallback.mAttributeCount, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
 
             // One of the read requests from Bob to Alice should be evicted.
             // We should have only one 1 active read handler, since the transaction from Alice to Bob has finished already, and one
             // of two Bob to Alice transactions has been evicted.
-            NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == 1);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), 1u);
 
             // Note: Larger read handler will be evicted before evicting the younger one.
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
-                                            [&]() { return backgroundReadCallback2.reportsReceived > 0; });
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback2.reportsReceived > 0);
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
+                                                   [&]() { return backgroundReadCallback2.reportsReceived > 0; });
+            EXPECT_GT(backgroundReadCallback2.reportsReceived, 0);
         });
 
     // The following tests are the cases of read transactions on PASE sessions.
@@ -4264,42 +4189,41 @@
             TestPerpetualListReadCallback backgroundReadCallback3;
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback1, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback2, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionAliceToBob(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionAliceToBob(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback3, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0 &&
                     backgroundReadCallback3.reportsReceived > 0;
             });
-            NL_TEST_ASSERT(apSuite,
-                           backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0 &&
-                               backgroundReadCallback3.reportsReceived > 0);
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0 &&
+                        backgroundReadCallback3.reportsReceived > 0);
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionCharlieToDavid(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
+                mpContext->GetSessionCharlieToDavid(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be accepted.
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError == 0);
-            NL_TEST_ASSERT(apSuite, readCallback.mOnDone == 1);
-            NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
+            EXPECT_EQ(readCallback.mOnError, 0u);
+            EXPECT_EQ(readCallback.mOnDone, 1u);
+            EXPECT_EQ(readCallback.mAttributeCount, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
             // Should evict one read request from Bob fabric for enough resources.
-            NL_TEST_ASSERT(apSuite,
-                           app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                               app::ReadHandler::InteractionType::Read, ctx.GetAliceFabricIndex()) == 1);
-            NL_TEST_ASSERT(apSuite,
-                           app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                               app::ReadHandler::InteractionType::Read, ctx.GetBobFabricIndex()) == 1);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read,
+                                                                                           mpContext->GetAliceFabricIndex()),
+                      1u);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read,
+                                                                                           mpContext->GetBobFabricIndex()),
+                      1u);
         });
 
     // Case 5.2: The device's fabric table is not full, PASE sessions are counted as a "valid" fabric and can evict existing read
@@ -4319,42 +4243,41 @@
             TestPerpetualListReadCallback backgroundReadCallback3;
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionAliceToBob(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionAliceToBob(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback1, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionAliceToBob(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionAliceToBob(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback2, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback3, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0 &&
                     backgroundReadCallback3.reportsReceived > 0;
             });
-            NL_TEST_ASSERT(apSuite,
-                           backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0 &&
-                               backgroundReadCallback3.reportsReceived > 0);
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0 &&
+                        backgroundReadCallback3.reportsReceived > 0);
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionCharlieToDavid(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
+                mpContext->GetSessionCharlieToDavid(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be accepted.
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError == 0);
-            NL_TEST_ASSERT(apSuite, readCallback.mOnDone == 1);
-            NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
+            EXPECT_EQ(readCallback.mOnError, 0u);
+            EXPECT_EQ(readCallback.mOnDone, 1u);
+            EXPECT_EQ(readCallback.mAttributeCount, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
             // Should evict one read request from Bob fabric for enough resources.
-            NL_TEST_ASSERT(apSuite,
-                           app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                               app::ReadHandler::InteractionType::Read, ctx.GetAliceFabricIndex()) == 1);
-            NL_TEST_ASSERT(apSuite,
-                           app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                               app::ReadHandler::InteractionType::Read, ctx.GetBobFabricIndex()) == 1);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read,
+                                                                                           mpContext->GetAliceFabricIndex()),
+                      1u);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read,
+                                                                                           mpContext->GetBobFabricIndex()),
+                      1u);
         });
 
     // Case 6: The device's fabric table is full, PASE sessions won't be counted as a valid fabric and cannot evict existing read
@@ -4372,44 +4295,43 @@
             TestPerpetualListReadCallback backgroundReadCallback3;
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback1, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback2, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionAliceToBob(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionAliceToBob(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback3, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0 &&
                     backgroundReadCallback3.reportsReceived > 0;
             });
-            NL_TEST_ASSERT(apSuite,
-                           backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0 &&
-                               backgroundReadCallback3.reportsReceived > 0);
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0 &&
+                        backgroundReadCallback3.reportsReceived > 0);
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionCharlieToDavid(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
+                mpContext->GetSessionCharlieToDavid(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be rejected.
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError == 1);
-            NL_TEST_ASSERT(apSuite, readCallback.mLastError == CHIP_IM_GLOBAL_STATUS(Busy));
+            EXPECT_EQ(readCallback.mOnError, 1u);
+            EXPECT_EQ(readCallback.mLastError, CHIP_IM_GLOBAL_STATUS(Busy));
             // Should evict one read request from Bob fabric for enough resources.
-            NL_TEST_ASSERT(apSuite,
-                           app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                               app::ReadHandler::InteractionType::Read, ctx.GetAliceFabricIndex()) == 2);
-            NL_TEST_ASSERT(apSuite,
-                           app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                               app::ReadHandler::InteractionType::Read, ctx.GetBobFabricIndex()) == 1);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read,
+                                                                                           mpContext->GetAliceFabricIndex()),
+                      2u);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read,
+                                                                                           mpContext->GetBobFabricIndex()),
+                      1u);
         });
 
     // Case 7: We will accept read transactions on PASE session when the fabric table is full but we have enough resources for it.
@@ -4426,38 +4348,38 @@
             TestPerpetualListReadCallback backgroundReadCallback2;
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback1, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionAliceToBob(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionAliceToBob(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback2, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0;
             });
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionCharlieToDavid(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
+                mpContext->GetSessionCharlieToDavid(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
 
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be accepted.
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError == 0);
-            NL_TEST_ASSERT(apSuite, readCallback.mOnDone == 1);
-            NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
+            EXPECT_EQ(readCallback.mOnError, 0u);
+            EXPECT_EQ(readCallback.mOnDone, 1u);
+            EXPECT_EQ(readCallback.mAttributeCount, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
             // No read transactions should be evicted.
-            NL_TEST_ASSERT(apSuite,
-                           app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                               app::ReadHandler::InteractionType::Read, ctx.GetAliceFabricIndex()) == 1);
-            NL_TEST_ASSERT(apSuite,
-                           app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                               app::ReadHandler::InteractionType::Read, ctx.GetBobFabricIndex()) == 1);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read,
+                                                                                           mpContext->GetAliceFabricIndex()),
+                      1u);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read,
+                                                                                           mpContext->GetBobFabricIndex()),
+                      1u);
         });
 
     // Case 8.1: If the fabric table on the device is full, read transactions on PASE session will always be evicted when another
@@ -4474,34 +4396,33 @@
             TestPerpetualListReadCallback backgroundReadCallback2;
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionCharlieToDavid(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionCharlieToDavid(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback1, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionAliceToBob(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionAliceToBob(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback2, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0;
             });
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
+                mpContext->GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be accepted.
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError == 0);
-            NL_TEST_ASSERT(apSuite, readCallback.mOnDone == 1);
-            NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
+            EXPECT_EQ(readCallback.mOnError, 0u);
+            EXPECT_EQ(readCallback.mOnDone, 1u);
+            EXPECT_EQ(readCallback.mAttributeCount, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
             // Should evict the read request on PASE session for enough resources.
-            NL_TEST_ASSERT(
-                apSuite,
-                app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read) == 1);
-            NL_TEST_ASSERT(apSuite,
-                           app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                               app::ReadHandler::InteractionType::Read, kUndefinedFabricIndex) == 0);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read),
+                      1u);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read,
+                                                                                           kUndefinedFabricIndex),
+                      0u);
         });
 
     // Case 8.2: If the fabric table on the device is full, read transactions on PASE session will always be evicted when another
@@ -4519,35 +4440,34 @@
             TestPerpetualListReadCallback backgroundReadCallback2;
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionCharlieToDavid(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionCharlieToDavid(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback1, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionAliceToBob(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionAliceToBob(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback2, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0;
             });
-            NL_TEST_ASSERT(apSuite, backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
+            EXPECT_TRUE(backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionBobToAlice(), 1, 1,
+                mpContext->GetSessionBobToAlice(), 1, 1,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be accepted.
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError == 0);
-            NL_TEST_ASSERT(apSuite, readCallback.mOnDone == 1);
-            NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == 1);
+            EXPECT_EQ(readCallback.mOnError, 0u);
+            EXPECT_EQ(readCallback.mOnDone, 1u);
+            EXPECT_EQ(readCallback.mAttributeCount, 1u);
             // Should evict the read request on PASE session for enough resources.
-            NL_TEST_ASSERT(
-                apSuite,
-                app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read) == 1);
-            NL_TEST_ASSERT(apSuite,
-                           app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                               app::ReadHandler::InteractionType::Read, kUndefinedFabricIndex) == 0);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read),
+                      1u);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read,
+                                                                                           kUndefinedFabricIndex),
+                      0u);
         });
 
     // Case 9.1: If the fabric table on the device is not full, read transactions on PASE session will NOT be evicted when the
@@ -4566,41 +4486,39 @@
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionCharlieToDavid(), 1, 1, app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
+                mpContext->GetSessionCharlieToDavid(), 1, 1, app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                 app::ReadClient::InteractionType::Read, &backgroundReadCallbackForPASESession, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionAliceToBob(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionAliceToBob(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback1, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionAliceToBob(), 1, 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionAliceToBob(), 1, 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback2, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return backgroundReadCallbackForPASESession.reportsReceived > 0 && backgroundReadCallback1.reportsReceived > 0 &&
                     backgroundReadCallback2.reportsReceived > 0;
             });
-            NL_TEST_ASSERT(apSuite,
-                           backgroundReadCallbackForPASESession.reportsReceived > 0 &&
-                               backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0);
+            EXPECT_TRUE(backgroundReadCallbackForPASESession.reportsReceived > 0 && backgroundReadCallback1.reportsReceived > 0 &&
+                        backgroundReadCallback2.reportsReceived > 0);
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionBobToAlice(), 1, 1,
+                mpContext->GetSessionBobToAlice(), 1, 1,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be accepted.
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError == 0);
-            NL_TEST_ASSERT(apSuite, readCallback.mOnDone == 1);
-            NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == 1);
+            EXPECT_EQ(readCallback.mOnError, 0u);
+            EXPECT_EQ(readCallback.mOnDone, 1u);
+            EXPECT_EQ(readCallback.mAttributeCount, 1u);
 
             // The read handler on PASE session should not be evicted since the resources used by all PASE sessions are not
             // exceeding the resources guaranteed to a normal fabric.
-            NL_TEST_ASSERT(
-                apSuite,
-                app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read) == 2);
-            NL_TEST_ASSERT(apSuite,
-                           app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                               app::ReadHandler::InteractionType::Read, kUndefinedFabricIndex) == 1);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read),
+                      2u);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read,
+                                                                                           kUndefinedFabricIndex),
+                      1u);
         });
 
     // Case 9.2: If the fabric table on the device is not full, the read handlers from normal fabrics MAY be evicted before all read
@@ -4620,42 +4538,41 @@
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionCharlieToDavid(), 3, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest - 1,
+                mpContext->GetSessionCharlieToDavid(), 3, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest - 1,
                 app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1), app::ReadClient::InteractionType::Read,
                 &backgroundReadCallbackForPASESession, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionBobToAlice(), 3,
+            EstablishReadOrSubscriptions(mpContext->GetSessionBobToAlice(), 3,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback1, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
                            app::ReadHandler::InteractionType::Read) == 6;
             });
-            NL_TEST_ASSERT(apSuite,
-                           app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                               app::ReadHandler::InteractionType::Read, kUndefinedFabricIndex) == 3);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read,
+                                                                                           kUndefinedFabricIndex),
+                      3u);
 
             // We have to evict one read transaction on PASE session and one read transaction on Alice's fabric.
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
+                mpContext->GetSessionAliceToBob(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be accepted.
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError == 0);
-            NL_TEST_ASSERT(apSuite, readCallback.mOnDone == 1);
-            NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
+            EXPECT_EQ(readCallback.mOnError, 0u);
+            EXPECT_EQ(readCallback.mOnDone, 1u);
+            EXPECT_EQ(readCallback.mAttributeCount, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
 
             // No more than one read handler on PASE session should be evicted exceeding the resources guaranteed to a normal
             // fabric. Note: We are using ">=" here since it is also acceptable if we choose to evict one read transaction from
             // Alice fabric.
-            NL_TEST_ASSERT(
-                apSuite,
-                app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read) >= 4);
-            NL_TEST_ASSERT(apSuite,
-                           app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                               app::ReadHandler::InteractionType::Read, kUndefinedFabricIndex) >= 2);
+            EXPECT_GE(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read),
+                      4u);
+            EXPECT_GE(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read,
+                                                                                           kUndefinedFabricIndex),
+                      2u);
         });
 
     // Case 10: If the fabric table on the device is full, we won't evict read requests from normal fabrics before we have evicted
@@ -4674,55 +4591,53 @@
             std::vector<std::unique_ptr<app::ReadClient>> readClients;
 
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionCharlieToDavid(), 2, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest - 1,
+                mpContext->GetSessionCharlieToDavid(), 2, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest - 1,
                 app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1), app::ReadClient::InteractionType::Read,
                 &backgroundReadCallbackForPASESession, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionAliceToBob(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionAliceToBob(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback1, readClients);
-            EstablishReadOrSubscriptions(apSuite, ctx.GetSessionAliceToBob(), 1,
+            EstablishReadOrSubscriptions(mpContext->GetSessionAliceToBob(), 1,
                                          app::InteractionModelEngine::kMinSupportedPathsPerReadRequest + 1,
                                          app::AttributePathParams(kTestEndpointId, kPerpetualClusterId, 1),
                                          app::ReadClient::InteractionType::Read, &backgroundReadCallback2, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() {
                 return backgroundReadCallbackForPASESession.reportsReceived > 0 && backgroundReadCallback1.reportsReceived > 0 &&
                     backgroundReadCallback2.reportsReceived > 0 &&
                     app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read,
                                                                                          kUndefinedFabricIndex) == 2;
             });
-            NL_TEST_ASSERT(apSuite,
-                           backgroundReadCallbackForPASESession.reportsReceived > 0 &&
-                               backgroundReadCallback1.reportsReceived > 0 && backgroundReadCallback2.reportsReceived > 0 &&
-                               app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                                   app::ReadHandler::InteractionType::Read, kUndefinedFabricIndex) == 2);
+            EXPECT_TRUE(backgroundReadCallbackForPASESession.reportsReceived > 0 && backgroundReadCallback1.reportsReceived > 0 &&
+                        backgroundReadCallback2.reportsReceived > 0 &&
+                        app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
+                            app::ReadHandler::InteractionType::Read, kUndefinedFabricIndex) == 2);
 
             // To handle this read request, we must evict both read transactions from the PASE session.
             EstablishReadOrSubscriptions(
-                apSuite, ctx.GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
+                mpContext->GetSessionBobToAlice(), 1, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest,
                 app::AttributePathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id),
                 app::ReadClient::InteractionType::Read, &readCallback, readClients);
-            ctx.GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
+            mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.mOnDone != 0; });
 
             // The new read request should be accepted.
-            NL_TEST_ASSERT(apSuite, readCallback.mOnError == 0);
-            NL_TEST_ASSERT(apSuite, readCallback.mOnDone == 1);
-            NL_TEST_ASSERT(apSuite, readCallback.mAttributeCount == app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
+            EXPECT_EQ(readCallback.mOnError, 0u);
+            EXPECT_EQ(readCallback.mOnDone, 1u);
+            EXPECT_EQ(readCallback.mAttributeCount, app::InteractionModelEngine::kMinSupportedPathsPerReadRequest);
 
             // The read handler on PASE session should be evicted, and the read transactions on a normal fabric should be untouched
             // although it is oversized.
-            NL_TEST_ASSERT(
-                apSuite,
-                app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read) == 2);
-            NL_TEST_ASSERT(apSuite,
-                           app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(
-                               app::ReadHandler::InteractionType::Read, kUndefinedFabricIndex) == 0);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read),
+                      2u);
+            EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(app::ReadHandler::InteractionType::Read,
+                                                                                           kUndefinedFabricIndex),
+                      0u);
         });
 
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
     app::InteractionModelEngine::GetInstance()->SetForceHandlerQuota(false);
     app::InteractionModelEngine::GetInstance()->SetConfigMaxFabrics(-1);
     app::InteractionModelEngine::GetInstance()->SetHandlerCapacityForReads(-1);
@@ -4732,20 +4647,18 @@
 // Needs to be larger than our plausible path pool.
 constexpr size_t sTooLargePathCount = 200;
 
-void TestReadInteraction::TestReadHandler_TooManyPaths(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_TooManyPaths)
 {
     using namespace chip::app;
 
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
-
-    chip::Messaging::ReliableMessageMgr * rm = ctx.GetExchangeManager().GetReliableMessageMgr();
+    chip::Messaging::ReliableMessageMgr * rm = mpContext->GetExchangeManager().GetReliableMessageMgr();
     // Shouldn't have anything in the retransmit table when starting the test.
-    NL_TEST_ASSERT(apSuite, rm->TestGetCountRetransTable() == 0);
+    EXPECT_EQ(rm->TestGetCountRetransTable(), 0);
 
     auto * engine = InteractionModelEngine::GetInstance();
     engine->SetForceHandlerQuota(true);
 
-    ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice());
+    ReadPrepareParams readPrepareParams(mpContext->GetSessionBobToAlice());
     // Needs to be larger than our plausible path pool.
     chip::app::AttributePathParams attributePathParams[sTooLargePathCount];
     readPrepareParams.mpAttributePathParamsList    = attributePathParams;
@@ -4753,93 +4666,90 @@
 
     {
         MockInteractionModelApp delegate;
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 0);
-        NL_TEST_ASSERT(apSuite, !delegate.mReadError);
-        ReadClient readClient(InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(), delegate,
+        EXPECT_EQ(delegate.mNumAttributeResponse, 0);
+        EXPECT_FALSE(delegate.mReadError);
+        ReadClient readClient(InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(), delegate,
                               ReadClient::InteractionType::Read);
 
         CHIP_ERROR err = readClient.SendRequest(readPrepareParams);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
+        mpContext->DrainAndServiceIO();
 
-        NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 0);
-        NL_TEST_ASSERT(apSuite, delegate.mReadError);
+        EXPECT_EQ(delegate.mNumAttributeResponse, 0);
+        EXPECT_TRUE(delegate.mReadError);
 
         StatusIB status(delegate.mError);
-        NL_TEST_ASSERT(apSuite, status.mStatus == Protocols::InteractionModel::Status::PathsExhausted);
+        EXPECT_EQ(status.mStatus, Protocols::InteractionModel::Status::PathsExhausted);
     }
 
-    NL_TEST_ASSERT(apSuite, engine->GetNumActiveReadClients() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(engine->GetNumActiveReadClients(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
     engine->SetForceHandlerQuota(false);
 }
 
-void TestReadInteraction::TestReadHandler_TwoParallelReadsSecondTooManyPaths(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_TwoParallelReadsSecondTooManyPaths)
 {
     using namespace chip::app;
 
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
-
-    chip::Messaging::ReliableMessageMgr * rm = ctx.GetExchangeManager().GetReliableMessageMgr();
+    chip::Messaging::ReliableMessageMgr * rm = mpContext->GetExchangeManager().GetReliableMessageMgr();
     // Shouldn't have anything in the retransmit table when starting the test.
-    NL_TEST_ASSERT(apSuite, rm->TestGetCountRetransTable() == 0);
+    EXPECT_EQ(rm->TestGetCountRetransTable(), 0);
 
     auto * engine = InteractionModelEngine::GetInstance();
     engine->SetForceHandlerQuota(true);
 
     {
         MockInteractionModelApp delegate1;
-        NL_TEST_ASSERT(apSuite, delegate1.mNumAttributeResponse == 0);
-        NL_TEST_ASSERT(apSuite, !delegate1.mReadError);
-        ReadClient readClient1(InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(), delegate1,
+        EXPECT_EQ(delegate1.mNumAttributeResponse, 0);
+        EXPECT_FALSE(delegate1.mReadError);
+        ReadClient readClient1(InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(), delegate1,
                                ReadClient::InteractionType::Read);
 
         MockInteractionModelApp delegate2;
-        NL_TEST_ASSERT(apSuite, delegate2.mNumAttributeResponse == 0);
-        NL_TEST_ASSERT(apSuite, !delegate2.mReadError);
-        ReadClient readClient2(InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(), delegate2,
+        EXPECT_EQ(delegate2.mNumAttributeResponse, 0);
+        EXPECT_FALSE(delegate2.mReadError);
+        ReadClient readClient2(InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(), delegate2,
                                ReadClient::InteractionType::Read);
 
-        ReadPrepareParams readPrepareParams1(ctx.GetSessionBobToAlice());
+        ReadPrepareParams readPrepareParams1(mpContext->GetSessionBobToAlice());
         // Read full wildcard paths, repeat twice to ensure chunking.
         chip::app::AttributePathParams attributePathParams1[2];
         readPrepareParams1.mpAttributePathParamsList    = attributePathParams1;
         readPrepareParams1.mAttributePathParamsListSize = ArraySize(attributePathParams1);
 
         CHIP_ERROR err = readClient1.SendRequest(readPrepareParams1);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ReadPrepareParams readPrepareParams2(ctx.GetSessionBobToAlice());
+        ReadPrepareParams readPrepareParams2(mpContext->GetSessionBobToAlice());
         // Read full wildcard paths, repeat twice to ensure chunking.
         chip::app::AttributePathParams attributePathParams2[sTooLargePathCount];
         readPrepareParams2.mpAttributePathParamsList    = attributePathParams2;
         readPrepareParams2.mAttributePathParamsListSize = ArraySize(attributePathParams2);
 
         err = readClient2.SendRequest(readPrepareParams2);
-        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+        EXPECT_EQ(err, CHIP_NO_ERROR);
 
-        ctx.DrainAndServiceIO();
+        mpContext->DrainAndServiceIO();
 
-        NL_TEST_ASSERT(apSuite, delegate1.mNumAttributeResponse != 0);
-        NL_TEST_ASSERT(apSuite, !delegate1.mReadError);
+        EXPECT_NE(delegate1.mNumAttributeResponse, 0);
+        EXPECT_FALSE(delegate1.mReadError);
 
-        NL_TEST_ASSERT(apSuite, delegate2.mNumAttributeResponse == 0);
-        NL_TEST_ASSERT(apSuite, delegate2.mReadError);
+        EXPECT_EQ(delegate2.mNumAttributeResponse, 0);
+        EXPECT_TRUE(delegate2.mReadError);
 
         StatusIB status(delegate2.mError);
-        NL_TEST_ASSERT(apSuite, status.mStatus == Protocols::InteractionModel::Status::PathsExhausted);
+        EXPECT_EQ(status.mStatus, Protocols::InteractionModel::Status::PathsExhausted);
     }
 
-    NL_TEST_ASSERT(apSuite, engine->GetNumActiveReadClients() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(engine->GetNumActiveReadClients(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
     engine->SetForceHandlerQuota(false);
 }
 
-void TestReadInteraction::TestReadAttribute_ManyDataValues(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadAttribute_ManyDataValues)
 {
-    TestContext & ctx   = *static_cast<TestContext *>(apContext);
-    auto sessionHandle  = ctx.GetSessionBobToAlice();
+    auto sessionHandle  = mpContext->GetSessionBobToAlice();
     size_t successCalls = 0;
     size_t failureCalls = 0;
 
@@ -4847,10 +4757,10 @@
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onSuccessCb = [apSuite, &successCalls](const app::ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
-        NL_TEST_ASSERT(apSuite, attributePath.mDataVersion.HasValue() && attributePath.mDataVersion.Value() == kDataVersion);
+    auto onSuccessCb = [&successCalls](const app::ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
+        EXPECT_TRUE(attributePath.mDataVersion.HasValue() && attributePath.mDataVersion.Value() == kDataVersion);
 
-        NL_TEST_ASSERT(apSuite, dataResponse);
+        EXPECT_TRUE(dataResponse);
         ++successCalls;
     };
 
@@ -4858,22 +4768,21 @@
     // not safe to do so.
     auto onFailureCb = [&failureCalls](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) { ++failureCalls; };
 
-    Controller::ReadAttribute<Clusters::UnitTesting::Attributes::Boolean::TypeInfo>(&ctx.GetExchangeManager(), sessionHandle,
+    Controller::ReadAttribute<Clusters::UnitTesting::Attributes::Boolean::TypeInfo>(&mpContext->GetExchangeManager(), sessionHandle,
                                                                                     kTestEndpointId, onSuccessCb, onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, successCalls == 1);
-    NL_TEST_ASSERT(apSuite, failureCalls == 0);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients() == 0);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(successCalls, 1u);
+    EXPECT_EQ(failureCalls, 0u);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients(), 0u);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestReadInteraction::TestReadAttribute_ManyDataValuesWrongPath(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadAttribute_ManyDataValuesWrongPath)
 {
-    TestContext & ctx   = *static_cast<TestContext *>(apContext);
-    auto sessionHandle  = ctx.GetSessionBobToAlice();
+    auto sessionHandle  = mpContext->GetSessionBobToAlice();
     size_t successCalls = 0;
     size_t failureCalls = 0;
 
@@ -4881,10 +4790,10 @@
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onSuccessCb = [apSuite, &successCalls](const app::ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
-        NL_TEST_ASSERT(apSuite, attributePath.mDataVersion.HasValue() && attributePath.mDataVersion.Value() == kDataVersion);
+    auto onSuccessCb = [&successCalls](const app::ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
+        EXPECT_TRUE(attributePath.mDataVersion.HasValue() && attributePath.mDataVersion.Value() == kDataVersion);
 
-        NL_TEST_ASSERT(apSuite, dataResponse);
+        EXPECT_TRUE(dataResponse);
         ++successCalls;
     };
 
@@ -4892,22 +4801,21 @@
     // not safe to do so.
     auto onFailureCb = [&failureCalls](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) { ++failureCalls; };
 
-    Controller::ReadAttribute<Clusters::UnitTesting::Attributes::Boolean::TypeInfo>(&ctx.GetExchangeManager(), sessionHandle,
+    Controller::ReadAttribute<Clusters::UnitTesting::Attributes::Boolean::TypeInfo>(&mpContext->GetExchangeManager(), sessionHandle,
                                                                                     kTestEndpointId, onSuccessCb, onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, successCalls == 0);
-    NL_TEST_ASSERT(apSuite, failureCalls == 1);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients() == 0);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(successCalls, 0u);
+    EXPECT_EQ(failureCalls, 1u);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients(), 0u);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestReadInteraction::TestReadAttribute_ManyErrors(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadAttribute_ManyErrors)
 {
-    TestContext & ctx   = *static_cast<TestContext *>(apContext);
-    auto sessionHandle  = ctx.GetSessionBobToAlice();
+    auto sessionHandle  = mpContext->GetSessionBobToAlice();
     size_t successCalls = 0;
     size_t failureCalls = 0;
 
@@ -4915,10 +4823,10 @@
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onSuccessCb = [apSuite, &successCalls](const app::ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
-        NL_TEST_ASSERT(apSuite, attributePath.mDataVersion.HasValue() && attributePath.mDataVersion.Value() == kDataVersion);
+    auto onSuccessCb = [&successCalls](const app::ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
+        EXPECT_TRUE(attributePath.mDataVersion.HasValue() && attributePath.mDataVersion.Value() == kDataVersion);
 
-        NL_TEST_ASSERT(apSuite, dataResponse);
+        EXPECT_TRUE(dataResponse);
         ++successCalls;
     };
 
@@ -4926,16 +4834,16 @@
     // not safe to do so.
     auto onFailureCb = [&failureCalls](const app::ConcreteDataAttributePath * attributePath, CHIP_ERROR aError) { ++failureCalls; };
 
-    Controller::ReadAttribute<Clusters::UnitTesting::Attributes::Boolean::TypeInfo>(&ctx.GetExchangeManager(), sessionHandle,
+    Controller::ReadAttribute<Clusters::UnitTesting::Attributes::Boolean::TypeInfo>(&mpContext->GetExchangeManager(), sessionHandle,
                                                                                     kTestEndpointId, onSuccessCb, onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, successCalls == 0);
-    NL_TEST_ASSERT(apSuite, failureCalls == 1);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients() == 0);
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(successCalls, 0u);
+    EXPECT_EQ(failureCalls, 1u);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadClients(), 0u);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
 //
@@ -4944,15 +4852,14 @@
 //
 // This should evict the previous subscription before sending back an error.
 //
-void TestReadInteraction::TestReadHandler_KeepSubscriptionTest(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestRead, TestReadHandler_KeepSubscriptionTest)
 {
     using namespace SubscriptionPathQuotaHelpers;
 
-    TestContext & ctx = *static_cast<TestContext *>(apContext);
     TestReadCallback readCallback;
     app::AttributePathParams pathParams(kTestEndpointId, Clusters::UnitTesting::Id, Clusters::UnitTesting::Attributes::Int16u::Id);
 
-    app::ReadPrepareParams readParam(ctx.GetSessionAliceToBob());
+    app::ReadPrepareParams readParam(mpContext->GetSessionAliceToBob());
     readParam.mpAttributePathParamsList    = &pathParams;
     readParam.mAttributePathParamsListSize = 1;
     readParam.mMaxIntervalCeilingSeconds   = 1;
@@ -4961,11 +4868,11 @@
     std::unique_ptr<app::ReadClient> readClient = std::make_unique<app::ReadClient>(
         app::InteractionModelEngine::GetInstance(), app::InteractionModelEngine::GetInstance()->GetExchangeManager(), readCallback,
         app::ReadClient::InteractionType::Subscribe);
-    NL_TEST_ASSERT(apSuite, readClient->SendRequest(readParam) == CHIP_NO_ERROR);
+    EXPECT_EQ(readClient->SendRequest(readParam), CHIP_NO_ERROR);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == 1);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), 1u);
 
     ChipLogProgress(DataManagement, "Issue another subscription that will evict the first sub...");
 
@@ -4973,17 +4880,17 @@
     readClient                             = std::make_unique<app::ReadClient>(app::InteractionModelEngine::GetInstance(),
                                                    app::InteractionModelEngine::GetInstance()->GetExchangeManager(), readCallback,
                                                    app::ReadClient::InteractionType::Subscribe);
-    NL_TEST_ASSERT(apSuite, readClient->SendRequest(readParam) == CHIP_NO_ERROR);
+    EXPECT_EQ(readClient->SendRequest(readParam), CHIP_NO_ERROR);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, readCallback.mOnError != 0);
+    EXPECT_EQ(app::InteractionModelEngine::GetInstance()->GetNumActiveReadHandlers(), 0u);
+    EXPECT_NE(readCallback.mOnError, 0u);
     app::InteractionModelEngine::GetInstance()->ShutdownActiveReads();
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 }
 
-System::Clock::Timeout TestReadInteraction::ComputeSubscriptionTimeout(System::Clock::Seconds16 aMaxInterval)
+System::Clock::Timeout TestRead::ComputeSubscriptionTimeout(System::Clock::Seconds16 aMaxInterval)
 {
     // Add 1000ms of slack to our max interval to make sure we hit the
     // subscription liveness timer.  100ms was tried in the past and is not
@@ -4996,75 +4903,4 @@
     return publisherTransmissionTimeout + aMaxInterval + System::Clock::Milliseconds32(1000);
 }
 
-// clang-format off
-const nlTest sTests[] =
-{
-    NL_TEST_DEF("TestReadAttributeResponse", TestReadInteraction::TestReadAttributeResponse),
-    NL_TEST_DEF("TestReadEventResponse", TestReadInteraction::TestReadEventResponse),
-    NL_TEST_DEF("TestReadAttributeError", TestReadInteraction::TestReadAttributeError),
-    NL_TEST_DEF("TestReadFabricScopedWithoutFabricFilter", TestReadInteraction::TestReadFabricScopedWithoutFabricFilter),
-    NL_TEST_DEF("TestReadFabricScopedWithFabricFilter", TestReadInteraction::TestReadFabricScopedWithFabricFilter),
-    NL_TEST_DEF("TestReadHandler_MultipleSubscriptions", TestReadInteraction::TestReadHandler_MultipleSubscriptions),
-    NL_TEST_DEF("TestReadHandler_SubscriptionAppRejection", TestReadInteraction::TestReadHandler_SubscriptionAppRejection),
-    NL_TEST_DEF("TestReadHandler_MultipleSubscriptionsWithDataVersionFilter", TestReadInteraction::TestReadHandler_MultipleSubscriptionsWithDataVersionFilter),
-    NL_TEST_DEF("TestReadHandler_MultipleReads", TestReadInteraction::TestReadHandler_MultipleReads),
-    NL_TEST_DEF("TestReadHandler_OneSubscribeMultipleReads", TestReadInteraction::TestReadHandler_OneSubscribeMultipleReads),
-    NL_TEST_DEF("TestReadHandler_TwoSubscribesMultipleReads", TestReadInteraction::TestReadHandler_TwoSubscribesMultipleReads),
-    NL_TEST_DEF("TestReadHandlerResourceExhaustion_MultipleReads", TestReadInteraction::TestReadHandlerResourceExhaustion_MultipleReads),
-    NL_TEST_DEF("TestReadAttributeTimeout", TestReadInteraction::TestReadAttributeTimeout),
-/*
-    Disabling SubscriptionReportingIntervals tests for ICD run.
-    These tests test the non-ICD behavior and cannot take into account that an ICD will always
-    change the max interval of a subscription.
-*/
-#if CHIP_CONFIG_ENABLE_ICD_SERVER != 1
-    NL_TEST_DEF("TestReadHandler_SubscriptionReportingIntervalsTest1", TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest1), // no good
-    NL_TEST_DEF("TestReadHandler_SubscriptionReportingIntervalsTest2", TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest2),
-    NL_TEST_DEF("TestReadHandler_SubscriptionReportingIntervalsTest3", TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest3),
-#endif // CHIP_CONFIG_ENABLE_ICD_SERVER
-    NL_TEST_DEF("TestReadHandler_SubscriptionReportingIntervalsTest4", TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest4),
-#if CHIP_CONFIG_ENABLE_ICD_SERVER != 1
-    NL_TEST_DEF("TestReadHandler_SubscriptionReportingIntervalsTest5", TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest5),
-    NL_TEST_DEF("TestReadHandler_SubscriptionReportingIntervalsTest6", TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest6),
-    NL_TEST_DEF("TestReadHandler_SubscriptionReportingIntervalsTest7", TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest7),
-#endif // CHIP_CONFIG_ENABLE_ICD_SERVER
-    NL_TEST_DEF("TestReadHandler_SubscriptionReportingIntervalsTest8", TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest8),
-    NL_TEST_DEF("TestReadHandler_SubscriptionReportingIntervalsTest9", TestReadInteraction::TestReadHandler_SubscriptionReportingIntervalsTest9),
-        NL_TEST_DEF("TestReadSubscribeAttributeResponseWithVersionOnlyCache", TestReadInteraction::TestReadSubscribeAttributeResponseWithVersionOnlyCache),
-    NL_TEST_DEF("TestReadSubscribeAttributeResponseWithCache", TestReadInteraction::TestReadSubscribeAttributeResponseWithCache),
-    NL_TEST_DEF("TestReadHandler_KillOverQuotaSubscriptions", TestReadInteraction::TestReadHandler_KillOverQuotaSubscriptions),
-    NL_TEST_DEF("TestReadHandler_KillOldestSubscriptions", TestReadInteraction::TestReadHandler_KillOldestSubscriptions),
-    NL_TEST_DEF("TestReadHandler_ParallelReads", TestReadInteraction::TestReadHandler_ParallelReads),
-    NL_TEST_DEF("TestReadHandler_TooManyPaths", TestReadInteraction::TestReadHandler_TooManyPaths),
-    NL_TEST_DEF("TestReadHandler_TwoParallelReadsSecondTooManyPaths", TestReadInteraction::TestReadHandler_TwoParallelReadsSecondTooManyPaths),
-    NL_TEST_DEF("TestReadAttribute_ManyDataValues", TestReadInteraction::TestReadAttribute_ManyDataValues),
-    NL_TEST_DEF("TestReadAttribute_ManyDataValuesWrongPath", TestReadInteraction::TestReadAttribute_ManyDataValuesWrongPath),
-    NL_TEST_DEF("TestReadAttribute_ManyErrors", TestReadInteraction::TestReadAttribute_ManyErrors),
-    NL_TEST_DEF("TestSubscribeAttributeDeniedNotExistPath", TestReadInteraction::TestSubscribeAttributeDeniedNotExistPath),
-    NL_TEST_DEF("TestResubscribeAttributeTimeout", TestReadInteraction::TestResubscribeAttributeTimeout),
-    NL_TEST_DEF("TestSubscribeAttributeTimeout", TestReadInteraction::TestSubscribeAttributeTimeout),
-    NL_TEST_DEF("TestReadHandler_KeepSubscriptionTest", TestReadInteraction::TestReadHandler_KeepSubscriptionTest),
-    NL_TEST_DEF("TestSubscribe_OnActiveModeNotification", TestReadInteraction::TestSubscribe_OnActiveModeNotification),
-    NL_TEST_DEF("TestSubscribe_ImmediatelyResubscriptionForLIT", TestReadInteraction::TestSubscribe_ImmediatelyResubscriptionForLIT),
-    NL_TEST_DEF("TestSubscribe_DynamicLITSubscription", TestReadInteraction::TestSubscribe_DynamicLITSubscription),
-    NL_TEST_SENTINEL()
-};
-// clang-format on
-
-nlTestSuite sSuite = {
-    "TestRead",
-    &sTests[0],
-    TestContext::nlTestSetUpTestSuite,
-    TestContext::nlTestTearDownTestSuite,
-    TestContext::nlTestSetUp,
-    TestContext::nlTestTearDown,
-};
-
 } // namespace
-
-int TestReadInteractionTest()
-{
-    return chip::ExecuteTestsWithContext<TestContext>(&sSuite);
-}
-
-CHIP_REGISTER_TEST_SUITE(TestReadInteractionTest)
diff --git a/src/controller/tests/data_model/TestWrite.cpp b/src/controller/tests/data_model/TestWrite.cpp
index 077c977..28f5797 100644
--- a/src/controller/tests/data_model/TestWrite.cpp
+++ b/src/controller/tests/data_model/TestWrite.cpp
@@ -16,6 +16,8 @@
  *    limitations under the License.
  */
 
+#include <gtest/gtest.h>
+
 #include "app-common/zap-generated/ids/Clusters.h"
 #include <app-common/zap-generated/cluster-objects.h>
 #include <app/AttributeValueDecoder.h>
@@ -23,11 +25,8 @@
 #include <app/tests/AppTestContext.h>
 #include <controller/WriteInteraction.h>
 #include <lib/core/ErrorStr.h>
-#include <lib/support/UnitTestContext.h>
-#include <lib/support/UnitTestRegistration.h>
 #include <lib/support/logging/CHIPLogging.h>
 #include <messaging/tests/MessagingContext.h>
-#include <nlunit-test.h>
 #include <protocols/interaction_model/Constants.h>
 
 using TestContext = chip::Test::AppContext;
@@ -185,25 +184,45 @@
 
 namespace {
 
-class TestWriteInteraction
+class TestWrite : public ::testing::Test
 {
 public:
-    TestWriteInteraction() {}
+    // Performs shared setup for all tests in the test suite
+    static void SetUpTestSuite()
+    {
+        if (mpContext == nullptr)
+        {
+            mpContext = new TestContext();
+            ASSERT_NE(mpContext, nullptr);
+        }
+        mpContext->SetUpTestSuite();
+    }
 
-    static void TestDataResponse(nlTestSuite * apSuite, void * apContext);
-    static void TestDataResponseWithAcceptedDataVersion(nlTestSuite * apSuite, void * apContext);
-    static void TestDataResponseWithRejectedDataVersion(nlTestSuite * apSuite, void * apContext);
-    static void TestAttributeError(nlTestSuite * apSuite, void * apContext);
-    static void TestFabricScopedAttributeWithoutFabricIndex(nlTestSuite * apSuite, void * apContext);
-    static void TestWriteTimeout(nlTestSuite * apSuite, void * apContext);
-    static void TestMultipleSuccessResponses(nlTestSuite * apSuite, void * apContext);
-    static void TestMultipleFailureResponses(nlTestSuite * apSuite, void * apContext);
+    // Performs shared teardown for all tests in the test suite
+    static void TearDownTestSuite()
+    {
+        mpContext->TearDownTestSuite();
+        if (mpContext != nullptr)
+        {
+            delete mpContext;
+            mpContext = nullptr;
+        }
+    }
+
+protected:
+    // Performs setup for each individual test in the test suite
+    void SetUp() { mpContext->SetUp(); }
+
+    // Performs teardown for each individual test in the test suite
+    void TearDown() { mpContext->TearDown(); }
+
+    static TestContext * mpContext;
 };
+TestContext * TestWrite::mpContext = nullptr;
 
-void TestWriteInteraction::TestDataResponse(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestWrite, TestDataResponse)
 {
-    TestContext & ctx       = *static_cast<TestContext *>(apContext);
-    auto sessionHandle      = ctx.GetSessionBobToAlice();
+    auto sessionHandle      = mpContext->GetSessionBobToAlice();
     bool onSuccessCbInvoked = false, onFailureCbInvoked = false;
     Clusters::UnitTesting::Structs::TestListStructOctet::Type valueBuf[4];
     Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo::Type value;
@@ -232,17 +251,16 @@
     chip::Controller::WriteAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
         sessionHandle, kTestEndpointId, value, onSuccessCb, onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, onSuccessCbInvoked && !onFailureCbInvoked);
-    NL_TEST_ASSERT(apSuite, chip::app::InteractionModelEngine::GetInstance()->GetNumActiveWriteHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(onSuccessCbInvoked && !onFailureCbInvoked);
+    EXPECT_EQ(chip::app::InteractionModelEngine::GetInstance()->GetNumActiveWriteHandlers(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestWriteInteraction::TestDataResponseWithAcceptedDataVersion(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestWrite, TestDataResponseWithAcceptedDataVersion)
 {
-    TestContext & ctx       = *static_cast<TestContext *>(apContext);
-    auto sessionHandle      = ctx.GetSessionBobToAlice();
+    auto sessionHandle      = mpContext->GetSessionBobToAlice();
     bool onSuccessCbInvoked = false, onFailureCbInvoked = false;
     Clusters::UnitTesting::Structs::TestListStructOctet::Type valueBuf[4];
     Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo::Type value;
@@ -273,17 +291,16 @@
     chip::Controller::WriteAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
         sessionHandle, kTestEndpointId, value, onSuccessCb, onFailureCb, nullptr, dataVersion);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, onSuccessCbInvoked && !onFailureCbInvoked);
-    NL_TEST_ASSERT(apSuite, chip::app::InteractionModelEngine::GetInstance()->GetNumActiveWriteHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(onSuccessCbInvoked && !onFailureCbInvoked);
+    EXPECT_EQ(chip::app::InteractionModelEngine::GetInstance()->GetNumActiveWriteHandlers(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestWriteInteraction::TestDataResponseWithRejectedDataVersion(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestWrite, TestDataResponseWithRejectedDataVersion)
 {
-    TestContext & ctx       = *static_cast<TestContext *>(apContext);
-    auto sessionHandle      = ctx.GetSessionBobToAlice();
+    auto sessionHandle      = mpContext->GetSessionBobToAlice();
     bool onSuccessCbInvoked = false, onFailureCbInvoked = false;
     Clusters::UnitTesting::Structs::TestListStructOctet::Type valueBuf[4];
     Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo::Type value;
@@ -313,17 +330,16 @@
     chip::Controller::WriteAttribute<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(
         sessionHandle, kTestEndpointId, value, onSuccessCb, onFailureCb, nullptr, dataVersion);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, !onSuccessCbInvoked && onFailureCbInvoked);
-    NL_TEST_ASSERT(apSuite, chip::app::InteractionModelEngine::GetInstance()->GetNumActiveWriteHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(!onSuccessCbInvoked && onFailureCbInvoked);
+    EXPECT_EQ(chip::app::InteractionModelEngine::GetInstance()->GetNumActiveWriteHandlers(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestWriteInteraction::TestAttributeError(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestWrite, TestAttributeError)
 {
-    TestContext & ctx       = *static_cast<TestContext *>(apContext);
-    auto sessionHandle      = ctx.GetSessionBobToAlice();
+    auto sessionHandle      = mpContext->GetSessionBobToAlice();
     bool onSuccessCbInvoked = false, onFailureCbInvoked = false;
     Attributes::ListStructOctetString::TypeInfo::Type value;
     Structs::TestListStructOctet::Type valueBuf[4];
@@ -345,25 +361,24 @@
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onFailureCb = [apSuite, &onFailureCbInvoked](const ConcreteAttributePath * attributePath, CHIP_ERROR aError) {
-        NL_TEST_ASSERT(apSuite, attributePath != nullptr);
+    auto onFailureCb = [&onFailureCbInvoked](const ConcreteAttributePath * attributePath, CHIP_ERROR aError) {
+        EXPECT_TRUE(attributePath != nullptr);
         onFailureCbInvoked = true;
     };
 
     Controller::WriteAttribute<Attributes::ListStructOctetString::TypeInfo>(sessionHandle, kTestEndpointId, value, onSuccessCb,
                                                                             onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, !onSuccessCbInvoked && onFailureCbInvoked);
-    NL_TEST_ASSERT(apSuite, InteractionModelEngine::GetInstance()->GetNumActiveWriteHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(!onSuccessCbInvoked && onFailureCbInvoked);
+    EXPECT_EQ(InteractionModelEngine::GetInstance()->GetNumActiveWriteHandlers(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestWriteInteraction::TestFabricScopedAttributeWithoutFabricIndex(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestWrite, TestFabricScopedAttributeWithoutFabricIndex)
 {
-    TestContext & ctx       = *static_cast<TestContext *>(apContext);
-    auto sessionHandle      = ctx.GetSessionBobToAlice();
+    auto sessionHandle      = mpContext->GetSessionBobToAlice();
     bool onSuccessCbInvoked = false, onFailureCbInvoked = false;
     Clusters::UnitTesting::Structs::TestFabricScoped::Type valueBuf[4];
     Clusters::UnitTesting::Attributes::ListFabricScoped::TypeInfo::Type value;
@@ -383,25 +398,24 @@
 
     // Passing of stack variables by reference is only safe because of synchronous completion of the interaction. Otherwise, it's
     // not safe to do so.
-    auto onFailureCb = [&onFailureCbInvoked, &apSuite](const ConcreteAttributePath * attributePath, CHIP_ERROR aError) {
-        NL_TEST_ASSERT(apSuite, aError == CHIP_IM_GLOBAL_STATUS(UnsupportedAccess));
+    auto onFailureCb = [&onFailureCbInvoked](const ConcreteAttributePath * attributePath, CHIP_ERROR aError) {
+        EXPECT_EQ(aError, CHIP_IM_GLOBAL_STATUS(UnsupportedAccess));
         onFailureCbInvoked = true;
     };
 
     chip::Controller::WriteAttribute<Clusters::UnitTesting::Attributes::ListFabricScoped::TypeInfo>(
         sessionHandle, kTestEndpointId, value, onSuccessCb, onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, !onSuccessCbInvoked && onFailureCbInvoked);
-    NL_TEST_ASSERT(apSuite, chip::app::InteractionModelEngine::GetInstance()->GetNumActiveWriteHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_TRUE(!onSuccessCbInvoked && onFailureCbInvoked);
+    EXPECT_EQ(chip::app::InteractionModelEngine::GetInstance()->GetNumActiveWriteHandlers(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestWriteInteraction::TestMultipleSuccessResponses(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestWrite, TestMultipleSuccessResponses)
 {
-    TestContext & ctx   = *static_cast<TestContext *>(apContext);
-    auto sessionHandle  = ctx.GetSessionBobToAlice();
+    auto sessionHandle  = mpContext->GetSessionBobToAlice();
     size_t successCalls = 0;
     size_t failureCalls = 0;
 
@@ -418,18 +432,17 @@
     chip::Controller::WriteAttribute<Clusters::UnitTesting::Attributes::Boolean::TypeInfo>(sessionHandle, kTestEndpointId, true,
                                                                                            onSuccessCb, onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, successCalls == 1);
-    NL_TEST_ASSERT(apSuite, failureCalls == 0);
-    NL_TEST_ASSERT(apSuite, chip::app::InteractionModelEngine::GetInstance()->GetNumActiveWriteHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(successCalls, 1u);
+    EXPECT_EQ(failureCalls, 0u);
+    EXPECT_EQ(chip::app::InteractionModelEngine::GetInstance()->GetNumActiveWriteHandlers(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-void TestWriteInteraction::TestMultipleFailureResponses(nlTestSuite * apSuite, void * apContext)
+TEST_F(TestWrite, TestMultipleFailureResponses)
 {
-    TestContext & ctx   = *static_cast<TestContext *>(apContext);
-    auto sessionHandle  = ctx.GetSessionBobToAlice();
+    auto sessionHandle  = mpContext->GetSessionBobToAlice();
     size_t successCalls = 0;
     size_t failureCalls = 0;
 
@@ -446,40 +459,12 @@
     chip::Controller::WriteAttribute<Clusters::UnitTesting::Attributes::Boolean::TypeInfo>(sessionHandle, kTestEndpointId, true,
                                                                                            onSuccessCb, onFailureCb);
 
-    ctx.DrainAndServiceIO();
+    mpContext->DrainAndServiceIO();
 
-    NL_TEST_ASSERT(apSuite, successCalls == 0);
-    NL_TEST_ASSERT(apSuite, failureCalls == 1);
-    NL_TEST_ASSERT(apSuite, chip::app::InteractionModelEngine::GetInstance()->GetNumActiveWriteHandlers() == 0);
-    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+    EXPECT_EQ(successCalls, 0u);
+    EXPECT_EQ(failureCalls, 1u);
+    EXPECT_EQ(chip::app::InteractionModelEngine::GetInstance()->GetNumActiveWriteHandlers(), 0u);
+    EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
 }
 
-const nlTest sTests[] = {
-    NL_TEST_DEF("TestDataResponse", TestWriteInteraction::TestDataResponse),
-    NL_TEST_DEF("TestDataResponseWithAcceptedDataVersion", TestWriteInteraction::TestDataResponseWithAcceptedDataVersion),
-    NL_TEST_DEF("TestDataResponseWithRejectedDataVersion", TestWriteInteraction::TestDataResponseWithRejectedDataVersion),
-    NL_TEST_DEF("TestAttributeError", TestWriteInteraction::TestAttributeError),
-    NL_TEST_DEF("TestWriteFabricScopedAttributeWithoutFabricIndex",
-                TestWriteInteraction::TestFabricScopedAttributeWithoutFabricIndex),
-    NL_TEST_DEF("TestMultipleSuccessResponses", TestWriteInteraction::TestMultipleSuccessResponses),
-    NL_TEST_DEF("TestMultipleFailureResponses", TestWriteInteraction::TestMultipleFailureResponses),
-    NL_TEST_SENTINEL(),
-};
-
-nlTestSuite sSuite = {
-    "TestWrite",
-    &sTests[0],
-    TestContext::nlTestSetUpTestSuite,
-    TestContext::nlTestTearDownTestSuite,
-    TestContext::nlTestSetUp,
-    TestContext::nlTestTearDown,
-};
-
 } // namespace
-
-int TestWriteInteractionTest()
-{
-    return chip::ExecuteTestsWithContext<TestContext>(&sSuite);
-}
-
-CHIP_REGISTER_TEST_SUITE(TestWriteInteractionTest)
diff --git a/src/test_driver/openiotsdk/unit-tests/test_components.txt b/src/test_driver/openiotsdk/unit-tests/test_components.txt
index a509669..8c59caf 100644
--- a/src/test_driver/openiotsdk/unit-tests/test_components.txt
+++ b/src/test_driver/openiotsdk/unit-tests/test_components.txt
@@ -17,4 +17,6 @@
 SupportTests
 UserDirectedCommissioningTests
 SecureChannelTests
-ICDServerTests
\ No newline at end of file
+ICDServerTests
+DataModelTests
+InetLayerTests
diff --git a/src/test_driver/openiotsdk/unit-tests/test_components_nl.txt b/src/test_driver/openiotsdk/unit-tests/test_components_nl.txt
index 941d486..55ebc4e 100644
--- a/src/test_driver/openiotsdk/unit-tests/test_components_nl.txt
+++ b/src/test_driver/openiotsdk/unit-tests/test_components_nl.txt
@@ -1,4 +1,3 @@
 AppTests
-DataModelTests
 MessagingLayerTests
 SecureChannelTestsNL