diff --git a/src/gpu/VirtualFluids_GPU/CMakeLists.txt b/src/gpu/VirtualFluids_GPU/CMakeLists.txt
index ed647cb406bca23ef90667b7d17171c7b3f46283..ffab484b28870fcc278e6aabbb4db618d30d0e99 100644
--- a/src/gpu/VirtualFluids_GPU/CMakeLists.txt
+++ b/src/gpu/VirtualFluids_GPU/CMakeLists.txt
@@ -24,5 +24,7 @@ if(BUILD_VF_UNIT_TESTS)
 	set_source_files_properties(DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp PROPERTIES LANGUAGE CUDA)
     set_source_files_properties(Communication/ExchangeData27Test.cpp PROPERTIES LANGUAGE CUDA)
     set_source_files_properties(BoundaryConditions/BoundaryConditionFactoryTest.cpp PROPERTIES LANGUAGE CUDA)
+    set_source_files_properties(Parameter/ParameterTest.cpp PROPERTIES LANGUAGE CUDA)
     target_include_directories(VirtualFluids_GPUTests PRIVATE "${VF_THIRD_DIR}/cuda_samples/")
+    target_include_directories(VirtualFluids_GPUTests PRIVATE "${VF_ROOT_DIR}/src/gpu/GridGenerator/")
 endif()
diff --git a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.cpp b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.cpp
index 696254c44e0fe1150ded8566650483878377928c..d59fa8d017069b665bd6b91f6cf1e685782fab24 100644
--- a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.cpp
+++ b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.cpp
@@ -445,7 +445,7 @@ void IndexRearrangementForStreams::findIfSparseIndexIsInSendIndicesAndAddToCommV
 void IndexRearrangementForStreams::findIndicesNotInCommAfterFtoC(const uint &numberOfSendOrRecvIndices,
                                                                  int *sendOrReceiveIndices,
                                                                  std::vector<int> &sendOrReceiveIndicesAfterFtoC,
-                                                                 std::vector<int> &sendOrIndicesOther) const
+                                                                 std::vector<int> &sendOrIndicesOther)
 {
     int sparseIndexSend;
     for (uint posInSendIndices = 0; posInSendIndices < numberOfSendOrRecvIndices; posInSendIndices++) {
diff --git a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.h b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.h
index 6102c2b10f70e54feb10c4b575cd8c07473b608b..0b0401d3424f7a953bf2fa92d0382fd9256a635a 100644
--- a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.h
+++ b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.h
@@ -62,9 +62,12 @@ protected:
                                                        std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const;
 
     //! \brief Initializes the send indices for the communication after the interpolation from fine to coarse
-    void initRecvIndicesForCommAfterFToCX(uint level, int indexOfProcessNeighbor, int direction, std::vector<uint>& recvIndicesForCommAfterFtoCPositions) const;
-    void initRecvIndicesForCommAfterFToCY(uint level, int indexOfProcessNeighbor, int direction, std::vector<uint>& recvIndicesForCommAfterFtoCPositions) const;
-    void initRecvIndicesForCommAfterFToCZ(uint level, int indexOfProcessNeighbor, int direction, std::vector<uint>& recvIndicesForCommAfterFtoCPositions) const;
+    void initRecvIndicesForCommAfterFToCX(uint level, int indexOfProcessNeighbor, int direction,
+                                          std::vector<uint> &recvIndicesForCommAfterFtoCPositions) const;
+    void initRecvIndicesForCommAfterFToCY(uint level, int indexOfProcessNeighbor, int direction,
+                                          std::vector<uint> &recvIndicesForCommAfterFtoCPositions) const;
+    void initRecvIndicesForCommAfterFToCZ(uint level, int indexOfProcessNeighbor, int direction,
+                                          std::vector<uint> &recvIndicesForCommAfterFtoCPositions) const;
 
     //! \brief Initializes pointers for reduced communication after the interpolation from fine to coarse by copying
     //! them from "normal" communication
@@ -82,10 +85,10 @@ protected:
 
     //! \brief The send indices are reordered for the communication after the interpolation from fine to coarse
     //! \details The indices of nodes which are part of the interpolation are moved to the front of vector with the send
-    //! indices. 
-    //! \pre para->getParH(level)->intCF needs to be inititalized 
+    //! indices.
+    //! \pre para->getParH(level)->intCF needs to be inititalized
     //! \param sendIndices is the pointer to the vector with the send indices, which will be reordered in this function
-    //! \param numberOfSendNodesAfterFtoC will be set in this method 
+    //! \param numberOfSendNodesAfterFtoC will be set in this method
     //! \param sendIndicesForCommAfterFtoCPositions stores each sendIndex's positions before reordering
     void reorderSendIndicesForCommAfterFtoC(int *sendIndices, int &numberOfSendNodesAfterFtoC, int direction,
                                             int level, std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const;
@@ -105,9 +108,9 @@ protected:
                                                         std::vector<int> &sendIndicesAfterFtoC,
                                                         std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const;
     //! \brief Find all indices which are not part of the communication after the interpolation from fine to coarse
-    void findIndicesNotInCommAfterFtoC(const uint &numberOfSendOrRecvIndices, int *sendOrReceiveIndices,
-                                       std::vector<int> &sendOrReceiveIndicesAfterFtoC,
-                                       std::vector<int> &sendOrIndicesOther) const;
+    static void findIndicesNotInCommAfterFtoC(const uint &numberOfSendOrRecvIndices, int *sendOrReceiveIndices,
+                                              std::vector<int> &sendOrReceiveIndicesAfterFtoC,
+                                              std::vector<int> &sendOrIndicesOther);
 
     //! \brief --> see reorderRecvIndicesForCommAfterFtoC
     void reorderRecvIndicesForCommAfterFtoCX(int direction, int level, int indexOfProcessNeighbor,
@@ -116,15 +119,16 @@ protected:
                                              std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const;
     void reorderRecvIndicesForCommAfterFtoCZ(int direction, int level, int indexOfProcessNeighbor,
                                              std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const;
-                                             
+
     //! \brief Reorder the receive indices in the same way that the send indices were reordered.
     //! \details When the send indices are reordered, the receive indices need to be reordered accordingly.
     //! \pre sendIndicesForCommAfterFtoCPositions should not be empty
-    //! \param recvIndices is the pointer to the vector with the receive indices, which will be reordered in this function
-    //! \param numberOfRecvNodesAfterFtoC will be set in this function
-    //! \param sendIndicesForCommAfterFtoCPositions stores each sendIndex's positions before reordering and is used to reorder the receive indices in the same way
-    void reorderRecvIndicesForCommAfterFtoC(int *recvIndices, int &numberOfRecvNodesAfterFtoC, int direction,
-                                            int level, std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const;
+    //! \param recvIndices is the pointer to the vector with the receive indices, which will be reordered in this
+    //! function \param numberOfRecvNodesAfterFtoC will be set in this function \param
+    //! sendIndicesForCommAfterFtoCPositions stores each sendIndex's positions before reordering and is used to reorder
+    //! the receive indices in the same way
+    void reorderRecvIndicesForCommAfterFtoC(int *recvIndices, int &numberOfRecvNodesAfterFtoC, int direction, int level,
+                                            std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const;
 
 private:
     std::shared_ptr<GridBuilder> builder;
@@ -133,6 +137,7 @@ private:
 
     // used for tests
     friend class IndexRearrangementForStreamsTest_reorderSendIndices;
+    friend class IndexRearrangementForStreamsTest_reorderRecvIndicesX;
     friend class IndexRearrangementForStreamsTest_exchangeIndicesForCommAfterFtoCX;
     friend class IndexRearrangementForStreamsTest_exchangeIndicesForCommAfterFtoCY;
     friend class IndexRearrangementForStreamsTest_exchangeIndicesForCommAfterFtoCZ;
diff --git a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp
index 3fe22394823e3c33d43f8fe8709d499e57ee66f9..0d4419755b391c28f5e985a9f08d67c2ce493d3f 100644
--- a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp
+++ b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp
@@ -34,6 +34,7 @@ private:
     LevelGridBuilderDouble() = default;
 
     uint numberOfSendIndices;
+    uint numberOfRecvIndices;
 
 public:
     LevelGridBuilderDouble(SPtr<Grid> grid) : LevelGridBuilder(), grid(grid){};
@@ -49,6 +50,14 @@ public:
     {
         return numberOfSendIndices;
     };
+    uint getNumberOfReceiveIndices(int direction, uint level) override
+    {
+        return numberOfRecvIndices;
+    };
+    void setNumberOfRecvIndices(uint numberOfRecvIndices)
+    {
+        this->numberOfRecvIndices = numberOfRecvIndices;
+    };
 };
 
 class GridImpDouble : public GridImp
@@ -542,3 +551,144 @@ TEST_F(IndexRearrangementForStreamsTest_exchangeIndicesForCommAfterFtoCZ, recvIn
     EXPECT_THAT(recvIndicesForCommAfterFtoCPositions.size(), testing::Eq(4));
     EXPECT_THAT(recvIndicesForCommAfterFtoCPositions, testing::Eq(expected));
 }
+
+//////////////////////////////////////////////////////////////////////////
+// Test reorderReceiveIndices
+//////////////////////////////////////////////////////////////////////////
+
+struct RecvIndicesForCommAfterFtoC {
+    // data to work on
+    std::vector<int> recvIndices = { 10, 11, 12, 13, 14, 15, 16 };
+    std::vector<uint> sendIndicesForCommAfterFtoCPositions = {};
+    const int level = 0;
+    const int direction = CommunicationDirections::MX;
+    const int numberOfProcessNeighbors = 1;
+    const int indexOfProcessNeighbor = 0;
+
+    // output data
+    int numberOfRecvNodesAfterFtoC;
+    // and reordered recvIndices
+};
+
+class IndexRearrangementForStreamsTest_reorderRecvIndicesX : public testing::Test
+{
+protected:
+    RecvIndicesForCommAfterFtoC ri;
+    SPtr<Parameter> para;
+    std::unique_ptr<IndexRearrangementForStreams> testSubject;
+
+    void setUpParaInX()
+    {
+        para->setNumberOfProcessNeighborsX(ri.numberOfProcessNeighbors, ri.level, "recv");
+        para->initProcessNeighborsAfterFtoCX(ri.level);
+        para->getParH(ri.level)->recvProcessNeighborX[ri.indexOfProcessNeighbor].index = ri.recvIndices.data();
+    }
+
+    void act()
+    {
+        testSubject->reorderRecvIndicesForCommAfterFtoC(ri.recvIndices.data(), ri.numberOfRecvNodesAfterFtoC,
+                                                        ri.direction, ri.level,
+                                                        ri.sendIndicesForCommAfterFtoCPositions);
+    };
+
+    void actWithX()
+    {
+        testSubject->reorderRecvIndicesForCommAfterFtoCX(ri.direction, ri.level, ri.indexOfProcessNeighbor,
+                                                         ri.sendIndicesForCommAfterFtoCPositions);
+    };
+
+private:
+    void SetUp() override
+    {
+        SPtr<GridImpDouble> grid =
+            GridImpDouble::makeShared(nullptr, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, Distribution(), 1);
+        std::shared_ptr<LevelGridBuilderDouble> builder = std::make_shared<LevelGridBuilderDouble>(grid);
+        builder->setNumberOfRecvIndices((uint)ri.recvIndices.size());
+
+        para = testingVF::createParameterForLevel(ri.level);
+
+        testSubject = std::make_unique<IndexRearrangementForStreams>(
+            IndexRearrangementForStreams(para, builder, vf::gpu::Communicator::getInstance()));
+    };
+};
+
+TEST_F(IndexRearrangementForStreamsTest_reorderRecvIndicesX, noSendIndicesForCommunicationAfterScalingFineToCoarse_receiveIndicesAreUnchanged)
+{
+    ri.sendIndicesForCommAfterFtoCPositions = {};
+    auto numberOfRecvNodesAfterFtoC_expected = ri.sendIndicesForCommAfterFtoCPositions.size();
+    std::vector<int> recvIndices_expected = { 10, 11, 12, 13, 14, 15, 16 };
+
+    act();
+    EXPECT_THAT(ri.numberOfRecvNodesAfterFtoC, testing::Eq(numberOfRecvNodesAfterFtoC_expected));
+    EXPECT_THAT(ri.recvIndices, testing::Eq(recvIndices_expected));
+}
+
+TEST_F(IndexRearrangementForStreamsTest_reorderRecvIndicesX, someSendIndicesForCommunicationAfterScalingFineToCoarse_receiveIndicesAreReorderedCorrectly)
+{
+    ri.sendIndicesForCommAfterFtoCPositions = { 0, 2, 4, 6 };
+    auto numberOfRecvNodesAfterFtoC_expected = ri.sendIndicesForCommAfterFtoCPositions.size();
+    std::vector<int> recvIndices_expected = { 10, 12, 14, 16, 11, 13, 15 };
+
+    act();
+    EXPECT_THAT(ri.numberOfRecvNodesAfterFtoC, testing::Eq(numberOfRecvNodesAfterFtoC_expected));
+    EXPECT_THAT(ri.recvIndices, testing::Eq(recvIndices_expected));
+}
+
+TEST_F(IndexRearrangementForStreamsTest_reorderRecvIndicesX, allIndicesAreSendIndicesForCommunicationAfterScalingFineToCoarse_receiveIndicesAreReorderedCorrectly)
+{
+    ri.sendIndicesForCommAfterFtoCPositions = { 0, 1, 2, 3, 4, 5, 6 };
+    auto numberOfRecvNodesAfterFtoC_expected = ri.sendIndicesForCommAfterFtoCPositions.size();
+    std::vector<int> recvIndices_expected = { 10, 11, 12, 13, 14, 15, 16 };
+
+    act();
+    EXPECT_THAT(ri.numberOfRecvNodesAfterFtoC, testing::Eq(numberOfRecvNodesAfterFtoC_expected));
+    EXPECT_THAT(ri.recvIndices, testing::Eq(recvIndices_expected));
+}
+
+TEST_F(IndexRearrangementForStreamsTest_reorderRecvIndicesX, noSendIndicesForCommunicationAfterScalingFineToCoarseInX_receiveIndicesAreUnchanged)
+{
+    setUpParaInX();
+
+    ri.sendIndicesForCommAfterFtoCPositions = {};
+    auto numberOfRecvNodesAfterFtoC_expected = ri.sendIndicesForCommAfterFtoCPositions.size();
+    std::vector<int> recvIndices_expected = { 10, 11, 12, 13, 14, 15, 16 };
+
+    this->actWithX();
+
+    EXPECT_THAT(para->getParH(ri.level)->recvProcessNeighborsAfterFtoCX[ri.indexOfProcessNeighbor].numberOfNodes,
+                testing::Eq(numberOfRecvNodesAfterFtoC_expected));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(ri.level)->recvProcessNeighborX[ri.indexOfProcessNeighbor].index,
+                                recvIndices_expected));
+}
+
+TEST_F(IndexRearrangementForStreamsTest_reorderRecvIndicesX, someSendIndicesForCommunicationAfterScalingFineToCoarseInX_receiveIndicesAreReorderedCorrectly)
+{
+    setUpParaInX();
+
+    ri.sendIndicesForCommAfterFtoCPositions = { 0, 2, 4, 6 };
+    auto numberOfRecvNodesAfterFtoC_expected = ri.sendIndicesForCommAfterFtoCPositions.size();
+    std::vector<int> recvIndices_expected = { 10, 12, 14, 16, 11, 13, 15 };
+
+    actWithX();
+
+    EXPECT_THAT(para->getParH(ri.level)->recvProcessNeighborsAfterFtoCX[ri.indexOfProcessNeighbor].numberOfNodes,
+                testing::Eq(numberOfRecvNodesAfterFtoC_expected));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(ri.level)->recvProcessNeighborX[ri.indexOfProcessNeighbor].index,
+                                recvIndices_expected));
+}
+
+TEST_F(IndexRearrangementForStreamsTest_reorderRecvIndicesX, allIndicesAreSendIndicesForCommunicationAfterScalingFineToCoarseInX_receiveIndicesAreReorderedCorrectly)
+{
+    setUpParaInX();
+
+    ri.sendIndicesForCommAfterFtoCPositions = { 0, 1, 2, 3, 4, 5, 6 };
+    auto numberOfRecvNodesAfterFtoC_expected = ri.sendIndicesForCommAfterFtoCPositions.size();
+    std::vector<int> recvIndices_expected = { 10, 11, 12, 13, 14, 15, 16 };
+
+    actWithX();
+
+    EXPECT_THAT(para->getParH(ri.level)->recvProcessNeighborsAfterFtoCX[ri.indexOfProcessNeighbor].numberOfNodes,
+                testing::Eq(numberOfRecvNodesAfterFtoC_expected));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(ri.level)->recvProcessNeighborX[ri.indexOfProcessNeighbor].index,
+                                recvIndices_expected));
+}
diff --git a/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactory.h b/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactory.h
index c6877cbfeffe5b32c0c2d336e46b02d68cd946a3..09f1a44166829f73c79cd839a7ecf75deae0e67e 100644
--- a/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactory.h
+++ b/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactory.h
@@ -161,15 +161,14 @@ public:
     // void setOutflowBoundaryCondition(...); // TODO:
     // https://git.rz.tu-bs.de/m.schoenherr/VirtualFluids_dev/-/issues/16
 
-    [[nodiscard]] boundaryCondition getVelocityBoundaryConditionPost(bool isGeometryBC = false) const;
+    [[nodiscard]] virtual boundaryCondition getVelocityBoundaryConditionPost(bool isGeometryBC = false) const;
     [[nodiscard]] boundaryCondition getNoSlipBoundaryConditionPost(bool isGeometryBC = false) const;
     [[nodiscard]] boundaryCondition getSlipBoundaryConditionPost(bool isGeometryBC = false) const;
     [[nodiscard]] boundaryCondition getPressureBoundaryConditionPre() const;
     [[nodiscard]] boundaryCondition getGeometryBoundaryConditionPost() const;
-    [[nodiscard]] precursorBoundaryConditionFunc getPrecursorBoundaryConditionPost() const;
-
 
     [[nodiscard]] boundaryConditionWithParameter getStressBoundaryConditionPost() const;
+    [[nodiscard]] precursorBoundaryConditionFunc getPrecursorBoundaryConditionPost() const;
 
 private:
     VelocityBC velocityBoundaryCondition = VelocityBC::NotSpecified;
diff --git a/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactoryTest.cpp b/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactoryTest.cpp
index 14d01d6df3334d767d97e8db87b7e2a9964022e3..a01b6af7abfebcdf488a66fc0c0ba1c9d3c81987 100644
--- a/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactoryTest.cpp
+++ b/src/gpu/VirtualFluids_GPU/Factories/BoundaryConditionFactoryTest.cpp
@@ -55,6 +55,8 @@ TEST(BoundaryConditionFactoryTest, defaultStressBC)
     EXPECT_THROW(bc(nullptr, nullptr, 0), std::bad_function_call);
 }
 
+// tests for boundary conditions which are set by the user (tests both set and get functions)
+
 bcFunction getVelocityBcTarget(BoundaryConditionFactory &bcFactory)
 {
     auto bc = bcFactory.getVelocityBoundaryConditionPost();
@@ -63,8 +65,6 @@ bcFunction getVelocityBcTarget(BoundaryConditionFactory &bcFactory)
     return bcTarget;
 }
 
-// tests for boundary conditions whcih are set by the user (tests both set and get functions)
-
 TEST(BoundaryConditionFactoryTest, velocityBC)
 {
     auto bcFactory = BoundaryConditionFactory();
diff --git a/src/gpu/VirtualFluids_GPU/KernelManager/BCKernelManagerTest.cpp b/src/gpu/VirtualFluids_GPU/KernelManager/BCKernelManagerTest.cpp
index a0e02112e821eedcfeb013d3465529f668309529..6b429d2d9c03e546286d3d2b0ced3612c0a4649a 100644
--- a/src/gpu/VirtualFluids_GPU/KernelManager/BCKernelManagerTest.cpp
+++ b/src/gpu/VirtualFluids_GPU/KernelManager/BCKernelManagerTest.cpp
@@ -1,3 +1,4 @@
+
 #include <gmock/gmock.h>
 #include <stdexcept>
 
@@ -18,44 +19,123 @@ protected:
     }
 };
 
-TEST_F(BCKernelManagerTest_BCsNotSpecified, velocityBoundaryConditionPost_NotSpecified)
+TEST_F(BCKernelManagerTest_BCsNotSpecified, velocityBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->velocityBC.numberOfBCnodes = 0;
+    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory));
+}
+
+TEST_F(BCKernelManagerTest_BCsNotSpecified, velocityBoundaryConditionPostNotSpecified_withBoundaryNodes_throws)
 {
     para->getParD(0)->velocityBC.numberOfBCnodes = 1;
     EXPECT_THROW(BCKernelManager(para, &bcFactory), std::runtime_error);
 }
 
-TEST_F(BCKernelManagerTest_BCsNotSpecified, noSlipBoundaryConditionPost_NotSpecified)
+TEST_F(BCKernelManagerTest_BCsNotSpecified, noSlipBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->noSlipBC.numberOfBCnodes = 0;
+    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory));
+}
+
+TEST_F(BCKernelManagerTest_BCsNotSpecified, noSlipBoundaryConditionPostNotSpecified_withBoundaryNodes_doesNotThrow)
 {
     para->getParD(0)->noSlipBC.numberOfBCnodes = 1;
     EXPECT_NO_THROW(BCKernelManager(para, &bcFactory)); // no throw, as a default is specified
 }
 
-TEST_F(BCKernelManagerTest_BCsNotSpecified, slipBoundaryConditionPost_NotSpecified)
+TEST_F(BCKernelManagerTest_BCsNotSpecified, slipBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->slipBC.numberOfBCnodes = 0;
+    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory));
+}
+
+TEST_F(BCKernelManagerTest_BCsNotSpecified, slipBoundaryConditionPostNotSpecified_withBoundaryNodes_throws)
 {
     para->getParD(0)->slipBC.numberOfBCnodes = 1;
     EXPECT_THROW(BCKernelManager(para, &bcFactory), std::runtime_error);
 }
 
-TEST_F(BCKernelManagerTest_BCsNotSpecified, pressureBoundaryConditionPre_NotSpecified)
+TEST_F(BCKernelManagerTest_BCsNotSpecified, pressureBoundaryConditionPreNotSpecified_noBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->pressureBC.numberOfBCnodes = 0;
+    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory));
+}
+
+TEST_F(BCKernelManagerTest_BCsNotSpecified, pressureBoundaryConditionPreNotSpecified_withBoundaryNodes_throws)
 {
     para->getParD(0)->pressureBC.numberOfBCnodes = 1;
     EXPECT_THROW(BCKernelManager(para, &bcFactory), std::runtime_error);
 }
 
-TEST_F(BCKernelManagerTest_BCsNotSpecified, geometryBoundaryConditionPost_NotSpecified)
+TEST_F(BCKernelManagerTest_BCsNotSpecified, geometryBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->geometryBC.numberOfBCnodes = 0;
+    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory));
+}
+
+TEST_F(BCKernelManagerTest_BCsNotSpecified, geometryBoundaryConditionPostNotSpecified_withBoundaryNodes_doesNotThrow)
 {
     para->getParD(0)->geometryBC.numberOfBCnodes = 1;
     EXPECT_NO_THROW(BCKernelManager(para, &bcFactory)); // no throw, as a default is specified
 }
 
-TEST_F(BCKernelManagerTest_BCsNotSpecified, stressBoundaryConditionPost_NotSpecified)
+TEST_F(BCKernelManagerTest_BCsNotSpecified, stressBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->stressBC.numberOfBCnodes = 0;
+    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory));
+}
+
+TEST_F(BCKernelManagerTest_BCsNotSpecified, stressBoundaryConditionPostNotSpecified_withBoundaryNodes_throws)
 {
     para->getParD(0)->stressBC.numberOfBCnodes = 1;
     EXPECT_THROW(BCKernelManager(para, &bcFactory), std::runtime_error);
 }
 
-TEST_F(BCKernelManagerTest_BCsNotSpecified, precursorBoundaryConditionPost_NotSpecified)
+TEST_F(BCKernelManagerTest_BCsNotSpecified, precursorBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->precursorBC.numberOfBCnodes = 0;
+    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory));
+}
+
+TEST_F(BCKernelManagerTest_BCsNotSpecified, precursorBoundaryConditionPostNotSpecified_withBoundaryNodes_throws)
 {
     para->getParD(0)->precursorBC.numberOfBCnodes = 1;
     EXPECT_THROW(BCKernelManager(para, &bcFactory), std::runtime_error);
 }
+
+class BoundaryConditionFactoryMock : public BoundaryConditionFactory
+{
+public:
+    mutable uint numberOfCalls = 0;
+
+    [[nodiscard]] boundaryCondition getVelocityBoundaryConditionPost(bool) const override
+    {
+        return [this](LBMSimulationParameter *, QforBoundaryConditions *) { numberOfCalls++; };
+    }
+};
+
+class BCKernelManagerTest_runBCs : public testing::Test
+{
+protected:
+    BoundaryConditionFactoryMock bcFactory;
+    SPtr<Parameter> para = std::make_shared<Parameter>();
+    UPtr<BCKernelManager> sut;
+
+    void SetUp() override
+    {
+        para->initLBMSimulationParameter();
+        sut = std::make_unique<BCKernelManager>(para, &bcFactory);
+    }
+};
+
+TEST_F(BCKernelManagerTest_runBCs, runVelocityBCKernelPost)
+{
+    para->getParD(0)->velocityBC.numberOfBCnodes = 1;
+    sut->runVelocityBCKernelPost(0);
+    EXPECT_THAT(bcFactory.numberOfCalls, testing::Eq(1));
+
+    bcFactory.numberOfCalls = 0;
+    para->getParD(0)->velocityBC.numberOfBCnodes = 0;
+    sut->runVelocityBCKernelPost(0);
+    EXPECT_THAT(bcFactory.numberOfCalls, testing::Eq(0));
+}
diff --git a/src/gpu/VirtualFluids_GPU/KernelManager/GridScalingKernelManagerTest.cpp b/src/gpu/VirtualFluids_GPU/KernelManager/GridScalingKernelManagerTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b86e167ca8d2f95897b1a87d4b850acbfbe8a1b3
--- /dev/null
+++ b/src/gpu/VirtualFluids_GPU/KernelManager/GridScalingKernelManagerTest.cpp
@@ -0,0 +1,81 @@
+#include <gmock/gmock.h>
+#include <stdexcept>
+
+#include "GridScalingKernelManager.h"
+#include "Factories/GridScalingFactory.h"
+#include "Parameter/Parameter.h"
+#include "PointerDefinitions.h"
+
+class GridScalingKernelManagerTest_Initialization : public testing::Test
+{
+protected:
+    GridScalingFactory scalingFactory;
+    SPtr<Parameter> para = std::make_shared<Parameter>();
+
+    void SetUp() override
+    {
+        para->setGridX({2, 8});
+        para->setGridY({2, 8});
+        para->setGridZ({2, 8});
+        para->setDistX({0, 0});
+        para->setDistY({0, 0});
+        para->setDistZ({0, 0});
+    }
+};
+
+TEST_F(GridScalingKernelManagerTest_Initialization, singleLevel_noScalingFactoryProvided_doesNotThrow)
+{
+    // only one level --> no scaling factory needed --> no error
+    para->initLBMSimulationParameter();
+    EXPECT_NO_THROW(GridScalingKernelManager(para, nullptr));
+}
+
+TEST_F(GridScalingKernelManagerTest_Initialization, singleLevel_scalingFactoryProvided_doesNotThrow)
+{
+    // only one level --> no scaling function needed --> no error
+    para->initLBMSimulationParameter();
+    EXPECT_NO_THROW(GridScalingKernelManager(para, &scalingFactory));
+}
+
+TEST_F(GridScalingKernelManagerTest_Initialization, singleLevel_scalingFactoryAndFunctionProvided_doesNotThrow)
+{
+    // only one level, but the user provided a scaling function anyway --> no error
+    para->initLBMSimulationParameter();
+    scalingFactory.setScalingFactory(GridScalingFactory::GridScaling::ScaleCompressible);
+    EXPECT_NO_THROW(GridScalingKernelManager(para, &scalingFactory));
+}
+
+TEST_F(GridScalingKernelManagerTest_Initialization, multipleLevels_notScalingFactoryProvided_throws)
+{
+    // multiple levels, but the user forgot the scaling factory --> error
+    para->setMaxLevel(2);
+    para->initLBMSimulationParameter();
+    EXPECT_THROW(GridScalingKernelManager(para, nullptr), std::runtime_error);
+}
+
+TEST_F(GridScalingKernelManagerTest_Initialization, multipleLevelWithoutInterpolationNodes_noScalingFunctionProvided_doesNotThrow)
+{
+    // multiple levels, but no interpolation nodes specified --> no scaling function needed --> no error
+    para->setMaxLevel(2);
+    para->initLBMSimulationParameter();
+    EXPECT_NO_THROW(GridScalingKernelManager(para, &scalingFactory));
+}
+
+TEST_F(GridScalingKernelManagerTest_Initialization, multipleLevelWithoutInterpolationNodes_scalingFunctionProvided_doesNotThrow)
+{
+    // multiple levels and NO interpolation nodes specified, but the user provided a scaling function anyway --> no error
+    para->setMaxLevel(2);
+    para->initLBMSimulationParameter();
+    scalingFactory.setScalingFactory(GridScalingFactory::GridScaling::ScaleRhoSq);
+    EXPECT_NO_THROW(GridScalingKernelManager(para, &scalingFactory));
+}
+
+TEST_F(GridScalingKernelManagerTest_Initialization, multipleLevelWithInterpolationNodes_noScalingFunctionProvided_throws)
+{
+    // multiple levels and interpolation nodes specified, but the user forgot to set the scalingFunction --> error
+    para->setMaxLevel(2);
+    para->initLBMSimulationParameter();
+    para->getParD(0)->fineToCoarse.numberOfCells = 100;
+    EXPECT_THROW(GridScalingKernelManager(para, &scalingFactory), std::runtime_error);
+}
+
diff --git a/src/gpu/VirtualFluids_GPU/Parameter/ParameterTest.cpp b/src/gpu/VirtualFluids_GPU/Parameter/ParameterTest.cpp
index b86d5657922deb9dca6e89574efc72766bcd16ce..bdd22ab27669363ef7b52ac1b16854e5fa25a3c8 100644
--- a/src/gpu/VirtualFluids_GPU/Parameter/ParameterTest.cpp
+++ b/src/gpu/VirtualFluids_GPU/Parameter/ParameterTest.cpp
@@ -4,9 +4,18 @@
 #include <iostream>
 #include <string>
 
+#include "LBM/Simulation.h"
 #include "Parameter.h"
+#include "PointerDefinitions.h"
 #include "basics/config/ConfigurationFile.h"
 
+#include "Factories/BoundaryConditionFactory.h"
+#include "Factories/GridScalingFactory.h"
+#include "Communication/Communicator.h"
+#include "DataStructureInitializer/GridReaderGenerator/GridGenerator.h"
+#include "GPU/CudaMemoryManager.h"
+#include "gpu/GridGenerator/grid/GridBuilder/MultipleGridBuilder.h"
+
 TEST(ParameterTest, passingEmptyFileWithoutPath_ShouldNotThrow)
 {
     // assuming that the config files is stored parallel to this file.
@@ -198,6 +207,72 @@ TEST(ParameterTest, userMissedSlashMultiGPU)
     EXPECT_THAT(para.getConcentration(), testing::Eq("gridPathTest/0/conc.dat"));
 }
 
+class MockGridGenerator : public GridGenerator
+{
+
+public:
+    MockGridGenerator(std::shared_ptr<GridBuilder> builder, std::shared_ptr<Parameter> para,
+                      std::shared_ptr<CudaMemoryManager> cudaMemoryManager, vf::gpu::Communicator &communicator)
+        : GridGenerator(builder, para, cudaMemoryManager, communicator)
+    {
+    }
+
+    void initalGridInformations() override
+    {
+        para->setGridX({ 2, 8 });
+        para->setGridY({ 2, 8 });
+        para->setGridZ({ 2, 8 });
+        para->setDistX({ 0, 0 });
+        para->setDistY({ 0, 0 });
+        para->setDistZ({ 0, 0 });
+    }
+    void allocArrays_CoordNeighborGeo() override{};
+    void setBoundingBox() override{};
+    void allocArrays_OffsetScale() override{};
+    void allocArrays_BoundaryValues() override{};
+    void allocArrays_BoundaryQs() override{};
+};
+
+TEST(ParameterTest, whenCreatingParameterClassWithGridRefinement_afterCallingInitLBMSimulationParameter_shouldNotThrow)
+{
+    auto para = std::make_shared<Parameter>();
+    para->setMaxLevel(2);
+
+    para->setGridX({ 2, 8 });
+    para->setGridY({ 2, 8 });
+    para->setGridZ({ 2, 8 });
+    para->setDistX({ 0, 0 });
+    para->setDistY({ 0, 0 });
+    para->setDistZ({ 0, 0 });
+
+    EXPECT_THAT(para->getParH(1), testing::Eq(nullptr)); // Parameter initialization incomplete
+    para->initLBMSimulationParameter();
+    EXPECT_THAT(para->getParH(1), testing::Ne(nullptr));
+}
+
+TEST(ParameterTest, whenCreatingParameterClassWithGridRefinement_afterCallingSimulationConstructor_shouldNotThrow)
+{
+    spdlog::set_level(spdlog::level::warn); // avoids logger spam in output
+
+    auto para = std::make_shared<Parameter>();
+    para->setMaxLevel(2);
+
+    SPtr<CudaMemoryManager> cudaMemoryManager = std::make_shared<CudaMemoryManager>(para);
+    vf::gpu::Communicator &communicator = vf::gpu::Communicator::getInstance();
+    auto gridFactory = GridFactory::make();
+    auto gridBuilder = MultipleGridBuilder::makeShared(gridFactory);
+    SPtr<GridProvider> gridGenerator =
+        std::make_shared<MockGridGenerator>(gridBuilder, para, cudaMemoryManager, communicator);
+    BoundaryConditionFactory bcFactory = BoundaryConditionFactory();
+    GridScalingFactory scalingFactory = GridScalingFactory();
+
+    EXPECT_THAT(para->getParH(1), testing::Eq(nullptr)); // Parameter initialization incomplete
+    // Simulation() calls para->initLBMSimulationParameter() --> that function completes the initialization of Parameter
+    Simulation sim(para, cudaMemoryManager, communicator, *gridGenerator, &bcFactory, &scalingFactory);
+    EXPECT_THAT(para->getParH(1), testing::Ne(nullptr));
+    EXPECT_NO_THROW(cudaMemoryManager->cudaAllocLevelForcing(1)); // throws if para->getParH(1) is a null pointer
+}
+
 class ParameterTestCumulantK17 : public testing::Test
 {
 protected: