diff --git a/test/gtest_ceres_manager.cpp b/test/gtest_ceres_manager.cpp
index 9b096f7c82d24aa1b2b939919f46a5190f8a65c0..57efea34c4fd4a4786dedf1f33d8d29c4e125705 100644
--- a/test/gtest_ceres_manager.cpp
+++ b/test/gtest_ceres_manager.cpp
@@ -401,7 +401,7 @@ TEST(CeresManager, AddRemoveFactor)
     // remove factor
     P->removeFactor(c);
 
-    ASSERT_TRUE(P->consumeFactorNotificationMap().empty()); // add+remove = empty
+    ASSERT_TRUE(P->getFactorNotificationMapSize() == 0); // add+remove = empty
 
     // update solver
     ceres_manager_ptr->update();
diff --git a/test/gtest_problem.cpp b/test/gtest_problem.cpp
index 213e29b9e8acb4c4af36da0c6365d1a538aa2d69..3b0ed8e164900db7f7bbe5e244e7a424f16758c9 100644
--- a/test/gtest_problem.cpp
+++ b/test/gtest_problem.cpp
@@ -9,6 +9,7 @@
 #include "base/utils/logging.h"
 
 #include "base/problem/problem.h"
+#include "base/solver/solver_manager.h"
 #include "base/sensor/sensor_base.h"
 #include "base/sensor/sensor_odom_3D.h"
 #include "base/processor/processor_odom_3D.h"
@@ -19,11 +20,36 @@
 using namespace wolf;
 using namespace Eigen;
 
+
+WOLF_PTR_TYPEDEFS(DummySolverManager);
+
+struct DummySolverManager : public SolverManager
+{
+  DummySolverManager(const ProblemPtr& _problem)
+    : SolverManager(_problem)
+  {
+    //
+  }
+  virtual void computeCovariances(const CovarianceBlocksToBeComputed blocks){};
+  virtual void computeCovariances(const StateBlockPtrList& st_list){};
+  virtual bool hasConverged(){return true;};
+  virtual SizeStd iterations(){return 0;};
+  virtual Scalar initialCost(){return 0;};
+  virtual Scalar finalCost(){return 0;};
+  virtual std::string solveImpl(const ReportVerbosity report_level){return std::string("");};
+  virtual void addFactor(const FactorBasePtr& fac_ptr){};
+  virtual void removeFactor(const FactorBasePtr& fac_ptr){};
+  virtual void addStateBlock(const StateBlockPtr& state_ptr){};
+  virtual void removeStateBlock(const StateBlockPtr& state_ptr){};
+  virtual void updateStateBlockStatus(const StateBlockPtr& state_ptr){};
+  virtual void updateStateBlockLocalParametrization(const StateBlockPtr& state_ptr){};
+};
+
 TEST(Problem, create)
 {
     ProblemPtr P = Problem::create("POV 3D");
 
-    // check double ointers to branches
+    // check double pointers to branches
     ASSERT_EQ(P, P->getHardware()->getProblem());
     ASSERT_EQ(P, P->getTrajectory()->getProblem());
     ASSERT_EQ(P, P->getMap()->getProblem());
@@ -109,20 +135,20 @@ TEST(Problem, SetOrigin_PO_2D)
     P->setPrior(x0, P0, t0, 1.0);
 
     // check that no sensor has been added
-    ASSERT_EQ(P->getHardware()->getSensorList().size(), (unsigned int) 0);
+    ASSERT_EQ(P->getHardware()->getSensorList().size(), (SizeStd) 0);
 
     // check that the state is correct
     ASSERT_TRUE((x0 - P->getCurrentState()).isMuchSmallerThan(1, Constants::EPS_SMALL));
 
     // check that we have one frame, one capture, one feature, one factor
     TrajectoryBasePtr T = P->getTrajectory();
-    ASSERT_EQ(T->getFrameList().size(), (unsigned int) 1);
+    ASSERT_EQ(T->getFrameList().size(), (SizeStd) 1);
     FrameBasePtr F = P->getLastFrame();
-    ASSERT_EQ(F->getCaptureList().size(), (unsigned int) 1);
+    ASSERT_EQ(F->getCaptureList().size(), (SizeStd) 1);
     CaptureBasePtr C = F->getCaptureList().front();
-    ASSERT_EQ(C->getFeatureList().size(), (unsigned int) 1);
+    ASSERT_EQ(C->getFeatureList().size(), (SizeStd) 1);
     FeatureBasePtr f = C->getFeatureList().front();
-    ASSERT_EQ(f->getFactorList().size(), (unsigned int) 1);
+    ASSERT_EQ(f->getFactorList().size(), (SizeStd) 1);
 
     // check that the factor is absolute (no pointers to other F, f, or L)
     FactorBasePtr c = f->getFactorList().front();
@@ -146,20 +172,20 @@ TEST(Problem, SetOrigin_PO_3D)
     P->setPrior(x0, P0, t0, 1.0);
 
     // check that no sensor has been added
-    ASSERT_EQ(P->getHardware()->getSensorList().size(), (unsigned int) 0);
+    ASSERT_EQ(P->getHardware()->getSensorList().size(), (SizeStd) 0);
 
     // check that the state is correct
     ASSERT_TRUE((x0 - P->getCurrentState()).isMuchSmallerThan(1, Constants::EPS_SMALL));
 
     // check that we have one frame, one capture, one feature, one factor
     TrajectoryBasePtr T = P->getTrajectory();
-    ASSERT_EQ(T->getFrameList().size(), (unsigned int) 1);
+    ASSERT_EQ(T->getFrameList().size(), (SizeStd) 1);
     FrameBasePtr F = P->getLastFrame();
-    ASSERT_EQ(F->getCaptureList().size(), (unsigned int) 1);
+    ASSERT_EQ(F->getCaptureList().size(), (SizeStd) 1);
     CaptureBasePtr C = F->getCaptureList().front();
-    ASSERT_EQ(C->getFeatureList().size(), (unsigned int) 1);
+    ASSERT_EQ(C->getFeatureList().size(), (SizeStd) 1);
     FeatureBasePtr f = C->getFeatureList().front();
-    ASSERT_EQ(f->getFactorList().size(), (unsigned int) 1);
+    ASSERT_EQ(f->getFactorList().size(), (SizeStd) 1);
 
     // check that the factor is absolute (no pointers to other F, f, or L)
     FactorBasePtr c = f->getFactorList().front();
@@ -190,7 +216,7 @@ TEST(Problem, emplaceFrame_factory)
     ASSERT_EQ(f2->getType().compare("POV 3D"), 0);
 
     // check that all frames are effectively in the trajectory
-    ASSERT_EQ(P->getTrajectory()->getFrameList().size(), (unsigned int) 3);
+    ASSERT_EQ(P->getTrajectory()->getFrameList().size(), (SizeStd) 3);
 
     // check that all frames are linked to Problem
     ASSERT_EQ(f0->getProblem(), P);
@@ -207,11 +233,11 @@ TEST(Problem, StateBlocks)
 
     // 2 state blocks, fixed
     SensorBasePtr    Sm = P->installSensor   ("ODOM 3D", "odometer",xs, wolf_root + "/src/examples/sensor_odom_3D.yaml");
-    ASSERT_EQ(P->consumeStateBlockNotificationMap().size(), (unsigned int) 2);
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd) 2);
 
     // 3 state blocks, fixed
     SensorBasePtr    St = P->installSensor   ("CAMERA", "camera",   xs, wolf_root + "/src/examples/camera_params_ueye_sim.yaml");
-    ASSERT_EQ(P->consumeStateBlockNotificationMap().size(), (unsigned int) (/*2 + */3)); // consume empties the notification map, so only should contain notification since last call
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd) (2 + 3));
 
     ProcessorParamsTrackerFeaturePtr params = std::make_shared<ProcessorParamsTrackerFeature>();
     params->time_tolerance            = 0.1;
@@ -223,16 +249,40 @@ TEST(Problem, StateBlocks)
     ProcessorBasePtr pm = P->installProcessor("ODOM 3D",            "odom integrator",      "odometer", wolf_root + "/src/examples/processor_odom_3D.yaml");
 
     // 2 state blocks, estimated
-    P->emplaceFrame("PO 3D", KEY_FRAME, xs, 0);
-    ASSERT_EQ(P->consumeStateBlockNotificationMap().size(), (unsigned int)(/*2 + 3*/ + 2)); // consume empties the notification map, so only should contain notification since last call
+    auto KF = P->emplaceFrame("PO 3D", KEY_FRAME, xs, 0);
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd)(2 + 3 + 2));
+
+    // Notifications
+    Notification notif;
+    ASSERT_TRUE(P->getStateBlockNotification(KF->getP(), notif));
+    ASSERT_EQ(notif, ADD);
+    ASSERT_TRUE(P->getStateBlockNotification(KF->getO(), notif));
+    ASSERT_EQ(notif, ADD);
 
     //    P->print(4,1,1,1);
 
     // change some SB properties
     St->unfixExtrinsics();
-    ASSERT_TRUE(P->consumeStateBlockNotificationMap().empty()); // changes in state_blocks status (fix/state/localparam) does not raise a notification in problem, only ADD/REMOVE
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd)(2 + 3 + 2)); // changes in state_blocks status (fix/state/localparam) does not raise a notification in problem, only ADD/REMOVE
 
     //    P->print(4,1,1,1);
+
+    // consume notifications
+    DummySolverManagerPtr SM = std::make_shared<DummySolverManager>(P);
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd)(2 + 3 + 2));
+    SM->update(); // calls P->consumeStateBlockNotificationMap();
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd) (0)); // consume empties the notification map
+
+    // remove frame
+    auto SB_P = KF->getP();
+    auto SB_O = KF->getO();
+    KF->remove();
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd)(2));
+    ASSERT_TRUE(P->getStateBlockNotification(SB_P, notif));
+    ASSERT_EQ(notif, REMOVE);
+    ASSERT_TRUE(P->getStateBlockNotification(SB_O, notif));
+    ASSERT_EQ(notif, REMOVE);
+
 }
 
 TEST(Problem, Covariances)
diff --git a/test/gtest_solver_manager.cpp b/test/gtest_solver_manager.cpp
index 9de5032b38af32cd564429fae2d0833c60817ef6..a38a7ee467e95f23a3f922c4b7bceb117e06cd14 100644
--- a/test/gtest_solver_manager.cpp
+++ b/test/gtest_solver_manager.cpp
@@ -450,9 +450,10 @@ TEST(SolverManager, AddUpdatedStateBlock)
     // add state_block
     P->addStateBlock(sb_ptr);
 
-    auto state_block_notification_map = P->consumeStateBlockNotificationMap();
-    ASSERT_EQ(state_block_notification_map.size(),1);
-    ASSERT_EQ(state_block_notification_map.begin()->second,ADD);
+    Notification notif;
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(),1);
+    ASSERT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    ASSERT_EQ(notif, ADD);
 
     // == Insert OTHER notifications ==
 
@@ -463,21 +464,25 @@ TEST(SolverManager, AddUpdatedStateBlock)
     // Fix --> FLAG
     sb_ptr->unfix();
 
-    ASSERT_TRUE(P->consumeStateBlockNotificationMap().empty()); // No new notifications (fix and set state are flags in sb)
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(),1); // No new notifications (fix and set state are flags in sb)
+
+    // == consume empties the notification map ==
+    solver_manager_ptr->update(); // it calls P->consumeStateBlockNotificationMap();
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(),0);
 
     // == When an REMOVE is notified: a REMOVE notification should be stored ==
 
     // remove state_block
     P->removeStateBlock(sb_ptr);
 
-    state_block_notification_map = P->consumeStateBlockNotificationMap();
-    ASSERT_EQ(state_block_notification_map.size(),1);
-    ASSERT_EQ(state_block_notification_map.begin()->second,REMOVE);
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(),1);
+    ASSERT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    ASSERT_EQ(notif, REMOVE);
 
     // == ADD + REMOVE: notification map should be empty ==
     P->addStateBlock(sb_ptr);
     P->removeStateBlock(sb_ptr);
-    ASSERT_TRUE(P->consumeStateBlockNotificationMap().empty());
+    ASSERT_TRUE(P->getStateBlockNotificationMapSize() == 0);
 
     // == UPDATES should clear the list of notifications ==
     // add state_block
@@ -486,7 +491,7 @@ TEST(SolverManager, AddUpdatedStateBlock)
     // update solver
     solver_manager_ptr->update();
 
-    ASSERT_TRUE(P->consumeStateBlockNotificationMap().empty()); // After solver_manager->update, notifications should be empty
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(),0); // After solver_manager->update, notifications should be empty
 }
 
 TEST(SolverManager, AddFactor)
@@ -504,6 +509,11 @@ TEST(SolverManager, AddFactor)
     FeatureBasePtr      f = C->addFeature(std::make_shared<FeatureBase>("ODOM 2D", Vector3s::Zero(), Matrix3s::Identity()));
     FactorPose2DPtr c = std::static_pointer_cast<FactorPose2D>(f->addFactor(std::make_shared<FactorPose2D>(f)));
 
+    // notification
+    Notification notif;
+    ASSERT_TRUE(P->getFactorNotification(c,notif));
+    ASSERT_EQ(notif, ADD);
+
     // update solver
     solver_manager_ptr->update();
 
@@ -532,6 +542,11 @@ TEST(SolverManager, RemoveFactor)
     // add factor
     P->removeFactor(c);
 
+    // notification
+    Notification notif;
+    ASSERT_TRUE(P->getFactorNotification(c,notif));
+    ASSERT_EQ(notif, REMOVE);
+
     // update solver
     solver_manager_ptr->update();
 
@@ -554,10 +569,17 @@ TEST(SolverManager, AddRemoveFactor)
     FeatureBasePtr      f = C->addFeature(std::make_shared<FeatureBase>("ODOM 2D", Vector3s::Zero(), Matrix3s::Identity()));
     FactorPose2DPtr c = std::static_pointer_cast<FactorPose2D>(f->addFactor(std::make_shared<FactorPose2D>(f)));
 
+    // notification
+    Notification notif;
+    ASSERT_TRUE(P->getFactorNotification(c,notif));
+    ASSERT_EQ(notif, ADD);
+
     // add factor
     P->removeFactor(c);
 
-    ASSERT_TRUE(P->consumeFactorNotificationMap().empty()); // ADD+REMOVE = empty
+    // notification
+    ASSERT_EQ(P->getFactorNotificationMapSize(), 0); // ADD+REMOVE cancels out
+    ASSERT_FALSE(P->getFactorNotification(c, notif)); // ADD+REMOVE cancels out
 
     // update solver
     solver_manager_ptr->update();
diff --git a/test/gtest_trajectory.cpp b/test/gtest_trajectory.cpp
index de582e26b0e3fbfa6ca61876e82d3b9870ea0ff8..ec2b314fc2dda90f7b6b53bb83713095fe46e257 100644
--- a/test/gtest_trajectory.cpp
+++ b/test/gtest_trajectory.cpp
@@ -9,6 +9,7 @@
 #include "base/utils/logging.h"
 
 #include "base/problem/problem.h"
+#include "base/solver/solver_manager.h"
 #include "base/trajectory/trajectory_base.h"
 #include "base/frame/frame_base.h"
 
@@ -16,45 +17,26 @@
 
 using namespace wolf;
 
-struct DummyNotificationProcessor
+struct DummySolverManager : public SolverManager
 {
-  DummyNotificationProcessor(ProblemPtr _problem)
-    : problem_(_problem)
+  DummySolverManager(const ProblemPtr& _problem)
+    : SolverManager(_problem)
   {
     //
   }
-
-  void update()
-  {
-    if (problem_ == nullptr)
-    {
-      FAIL() << "problem_ is nullptr !";
-    }
-
-    auto sb_noti_map = problem_->consumeStateBlockNotificationMap();
-    ASSERT_TRUE(problem_->consumeStateBlockNotificationMap().empty()); // consume should empty the notification map
-
-    while (!sb_noti_map.empty())
-    {
-        switch (sb_noti_map.begin()->second)
-        {
-          case ADD:
-          {
-            break;
-          }
-          case REMOVE:
-          {
-            break;
-          }
-          default:
-            throw std::runtime_error("SolverManager::update: State Block notification must be ADD or REMOVE.");
-        }
-        sb_noti_map.erase(sb_noti_map.begin());
-    }
-    ASSERT_TRUE(sb_noti_map.empty());
-  }
-
-  ProblemPtr problem_;
+  virtual void computeCovariances(const CovarianceBlocksToBeComputed blocks){};
+  virtual void computeCovariances(const StateBlockPtrList& st_list){};
+  virtual bool hasConverged(){return true;};
+  virtual SizeStd iterations(){return 0;};
+  virtual Scalar initialCost(){return 0;};
+  virtual Scalar finalCost(){return 0;};
+  virtual std::string solveImpl(const ReportVerbosity report_level){return std::string("");};
+  virtual void addFactor(const FactorBasePtr& fac_ptr){};
+  virtual void removeFactor(const FactorBasePtr& fac_ptr){};
+  virtual void addStateBlock(const StateBlockPtr& state_ptr){};
+  virtual void removeStateBlock(const StateBlockPtr& state_ptr){};
+  virtual void updateStateBlockStatus(const StateBlockPtr& state_ptr){};
+  virtual void updateStateBlockLocalParametrization(const StateBlockPtr& state_ptr){};
 };
 
 /// Set to true if you want debug info
@@ -103,7 +85,7 @@ TEST(TrajectoryBase, Add_Remove_Frame)
     ProblemPtr P = Problem::create("PO 2D");
     TrajectoryBasePtr T = P->getTrajectory();
 
-    DummyNotificationProcessor N(P);
+    DummySolverManager N(P);
 
     // Trajectory status:
     //  kf1   kf2    f3      frames
@@ -119,19 +101,20 @@ TEST(TrajectoryBase, Add_Remove_Frame)
     // add frames and keyframes
     T->addFrame(f1); // KF
     if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getFrameList().                 size(), (unsigned int) 1);
-    ASSERT_EQ(P->consumeStateBlockNotificationMap(). size(), (unsigned int) 2);
+    ASSERT_EQ(T->getFrameList().             size(), (SizeStd) 1);
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd) 2);
     std::cout << __LINE__ << std::endl;
 
     T->addFrame(f2); // KF
     if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getFrameList().                 size(), (unsigned int) 2);
+    ASSERT_EQ(T->getFrameList().             size(), (SizeStd) 2);
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd) 4);
     std::cout << __LINE__ << std::endl;
 
     T->addFrame(f3); // F (not KF so state blocks are not notified)
     if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getFrameList().                 size(), (unsigned int) 3);
-    ASSERT_EQ(P->consumeStateBlockNotificationMap(). size(), (unsigned int) 2); // consumeStateBlockNotificationMap empties the notification map, 2 state blocks were notified since last call to consumeStateBlockNotificationMap
+    ASSERT_EQ(T->getFrameList().             size(), (SizeStd) 3);
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd) 4);
     std::cout << __LINE__ << std::endl;
 
     ASSERT_EQ(T->getLastFrame()->id(), f3->id());
@@ -139,14 +122,14 @@ TEST(TrajectoryBase, Add_Remove_Frame)
     std::cout << __LINE__ << std::endl;
 
     N.update();
-    ASSERT_TRUE(P->consumeStateBlockNotificationMap().empty()); // consumeStateBlockNotificationMap was called in update() so it should be empty
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd) 0); // consumeStateBlockNotificationMap was called in update() so it should be empty
     std::cout << __LINE__ << std::endl;
 
     // remove frames and keyframes
     f2->remove(); // KF
     if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getFrameList().                 size(), (unsigned int) 2);
-    ASSERT_EQ(P->consumeStateBlockNotificationMap(). size(), (unsigned int) 2); // consumeStateBlockNotificationMap empties the notification map, 2 state blocks were notified since last call to consumeStateBlockNotificationMap
+    ASSERT_EQ(T->getFrameList().             size(), (SizeStd) 2);
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd) 2);
     std::cout << __LINE__ << std::endl;
 
     ASSERT_EQ(T->getLastFrame()->id(), f3->id());
@@ -155,19 +138,19 @@ TEST(TrajectoryBase, Add_Remove_Frame)
 
     f3->remove(); // F
     if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getFrameList().                 size(), (unsigned int) 1);
+    ASSERT_EQ(T->getFrameList().             size(), (SizeStd) 1);
     std::cout << __LINE__ << std::endl;
 
     ASSERT_EQ(T->getLastKeyFrame()->id(), f1->id());
 
     f1->remove(); // KF
     if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getFrameList().                 size(), (unsigned int) 0);
+    ASSERT_EQ(T->getFrameList().             size(), (SizeStd) 0);
     std::cout << __LINE__ << std::endl;
 
     N.update();
 
-    ASSERT_TRUE(P->consumeStateBlockNotificationMap().empty()); // consumeStateBlockNotificationMap was called in update() so it should be empty
+    ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd) 0); // consumeStateBlockNotificationMap was called in update() so it should be empty
     std::cout << __LINE__ << std::endl;
 }