diff --git a/dumux/flux/shallowwaterviscousflux.hh b/dumux/flux/shallowwaterviscousflux.hh
index ce0ce087f8ded89e8c903c5eff2a6ecb36b4e81b..592e4bcd6bd777c2b751815d407d773a50957843 100644
--- a/dumux/flux/shallowwaterviscousflux.hh
+++ b/dumux/flux/shallowwaterviscousflux.hh
@@ -28,6 +28,10 @@
 #include <algorithm>
 #include <utility>
 #include <type_traits>
+#include <array>
+
+#include <dune/common/std/type_traits.hh>
+#include <dune/common/exceptions.hh>
 
 #include <dumux/common/parameters.hh>
 #include <dumux/flux/fluxvariablescaching.hh>
@@ -35,6 +39,18 @@
 
 namespace Dumux {
 
+#ifndef DOXYGEN
+namespace Detail {
+// helper struct detecting if the user-defined spatial params class has a frictionLaw function
+template <typename T, typename ...Ts>
+using FrictionLawDetector = decltype(std::declval<T>().frictionLaw(std::declval<Ts>()...));
+
+template<class T, typename ...Args>
+static constexpr bool implementsFrictionLaw()
+{ return Dune::Std::is_detected<FrictionLawDetector, T, Args...>::value; }
+} // end namespace Detail
+#endif
+
 /*!
  * \ingroup Flux
  * \brief Computes the shallow water viscous momentum flux due to (turbulent) viscosity
@@ -88,7 +104,7 @@ public:
         const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
         const auto& outsideScv = fvGeometry.scv(scvf.outsideScvIdx());
 
-        const auto [gradU, gradV] = [&]()
+        const auto gradVelocity = [&]()
         {
             // The left (inside) and right (outside) states
             const auto velocityXLeft   = insideVolVars.velocity(0);
@@ -102,10 +118,10 @@ public:
             const auto distance = cellCenterToCellCenter.two_norm();
             const auto& unitNormal = scvf.unitOuterNormal();
             const auto direction = (unitNormal*cellCenterToCellCenter)/distance;
-            return std::make_pair(
+            return std::array<Scalar, 2>{
                 (velocityXRight-velocityXLeft)*direction/distance,
                 (velocityYRight-velocityYLeft)*direction/distance
-            );
+            };
         }();
 
         // Use a harmonic average of the depth at the interface.
@@ -114,7 +130,7 @@ public:
         const auto averageDepth = 2.0*(waterDepthLeft*waterDepthRight)/(waterDepthLeft + waterDepthRight);
 
         // compute the turbulent viscosity contribution
-        const Scalar turbViscosity = [&,gradU=gradU,gradV=gradV]()
+        const Scalar turbViscosity = [&]()
         {
             // The (constant) background turbulent viscosity
             static const auto turbBGViscosity = getParamFromGroup<Scalar>(problem.paramGroup(), "ShallowWater.TurbulentViscosity", 1.0e-6);
@@ -126,74 +142,84 @@ public:
             if (!useMixingLengthTurbulenceModel)
                 return turbBGViscosity;
 
-            // turbulence model based on mixing length
-            // Compute the turbulent viscosity using a combined horizonal/vertical mixing length approach
-            // Turbulence coefficients: vertical (Elder like) and horizontal (Smagorinsky like)
-            static const auto turbConstV = getParamFromGroup<Scalar>(problem.paramGroup(), "ShallowWater.VerticalCoefficientOfMixingLengthModel", 1.0);
-            static const auto turbConstH = getParamFromGroup<Scalar>(problem.paramGroup(), "ShallowWater.HorizontalCoefficientOfMixingLengthModel", 0.1);
-
-            /** The vertical (Elder-like) contribution to the turbulent viscosity scales with water depth \f[ h \f] and shear velocity \f[ u_{*} \f] :
-            *
-            * \f[
-            * \nu_t^v = c^v \frac{\kappa}{6} u_{*} h
-            * \f]
-            */
-            constexpr Scalar kappa = 0.41;
-            // Compute the average shear velocity on the face
-            const Scalar ustar = [&]()
+            using SpatialParams = typename Problem::SpatialParams;
+            using E = typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity;
+            using SCV = typename FVElementGeometry::SubControlVolume;
+            if constexpr (!Detail::implementsFrictionLaw<SpatialParams, E, SCV>())
+                DUNE_THROW(Dune::IOError, "Mixing length turbulence model enabled but spatial parameters do not implement the frictionLaw interface!");
+            else
             {
-                // Get the bottom shear stress in the two adjacent cells
-                // Note that element is not needed in spatialParams().frictionLaw (should be removed). For now we simply pass the same element twice
-                const auto& bottomShearStressInside = problem.spatialParams().frictionLaw(element, insideScv).shearStress(insideVolVars);
-                const auto& bottomShearStressOutside = problem.spatialParams().frictionLaw(element, outsideScv).shearStress(outsideVolVars);
-                const auto bottomShearStressInsideMag = bottomShearStressInside.two_norm();
-                const auto bottomShearStressOutsideMag = bottomShearStressOutside.two_norm();
-
-                // Use a harmonic average of the viscosity and the depth at the interface.
-                using std::max;
-                const auto averageBottomShearStress = 2.0*(bottomShearStressInsideMag*bottomShearStressOutsideMag)
-                        / max(1.0e-8,bottomShearStressInsideMag + bottomShearStressOutsideMag);
-
-                // Shear velocity possibly needed in mixing-length turbulence model in the computation of the diffusion flux
+                // turbulence model based on mixing length
+                // Compute the turbulent viscosity using a combined horizonal/vertical mixing length approach
+                // Turbulence coefficients: vertical (Elder like) and horizontal (Smagorinsky like)
+                static const auto turbConstV = getParamFromGroup<Scalar>(problem.paramGroup(), "ShallowWater.VerticalCoefficientOfMixingLengthModel", 1.0);
+                static const auto turbConstH = getParamFromGroup<Scalar>(problem.paramGroup(), "ShallowWater.HorizontalCoefficientOfMixingLengthModel", 0.1);
+
+                /** The vertical (Elder-like) contribution to the turbulent viscosity scales with water depth \f[ h \f] and shear velocity \f[ u_{*} \f] :
+                *
+                * \f[
+                * \nu_t^v = c^v \frac{\kappa}{6} u_{*} h
+                * \f]
+                */
+                constexpr Scalar kappa = 0.41;
+                // Compute the average shear velocity on the face
+                const Scalar ustar = [&]()
+                {
+                    // Get the bottom shear stress in the two adjacent cells
+                    // Note that element is not needed in spatialParams().frictionLaw (should be removed). For now we simply pass the same element twice
+                    const auto& bottomShearStressInside = problem.spatialParams().frictionLaw(element, insideScv).shearStress(insideVolVars);
+                    const auto& bottomShearStressOutside = problem.spatialParams().frictionLaw(element, outsideScv).shearStress(outsideVolVars);
+                    const auto bottomShearStressInsideMag = bottomShearStressInside.two_norm();
+                    const auto bottomShearStressOutsideMag = bottomShearStressOutside.two_norm();
+
+                    // Use a harmonic average of the viscosity and the depth at the interface.
+                    using std::max;
+                    const auto averageBottomShearStress = 2.0*(bottomShearStressInsideMag*bottomShearStressOutsideMag)
+                            / max(1.0e-8,bottomShearStressInsideMag + bottomShearStressOutsideMag);
+
+                    // Shear velocity possibly needed in mixing-length turbulence model in the computation of the diffusion flux
+                    using std::sqrt;
+                    return sqrt(averageBottomShearStress);
+                }();
+
+                const auto turbViscosityV = turbConstV * (kappa/6.0) * ustar * averageDepth;
+
+                /** The horizontal (Smagorinsky-like) contribution to the turbulent viscosity scales with the water depth (squared)
+                * and the magnitude of the stress (rate-of-strain) tensor:
+                *
+                * \f[
+                * nu_t^h = (c^h h)^2 \sqrt{ 2\left(\frac{\partial u}{\partial x}\right)^2 + \left(\frac{\partial u}{\partial y} + \frac{\partial v}{\partial x}\right)^2 + 2\left(\frac{\partial v}{\partial y}\right)^2 }
+                * \f]
+                *
+                * However, based on the velocity vectors in the direct neighbours of the volume face, it is not possible to compute all components of the stress tensor.
+                * Only the gradients of u and v in the direction of the vector between the cell centres is available.
+                * To avoid the reconstruction of the full velocity gradient tensor based on a larger stencil,
+                * the horizontal contribution to the eddy viscosity (in the mixing-length model) is computed using only the velocity gradients normal to the face:
+                *
+                * \f[
+                * \frac{\partial u}{\partial n} , \frac{\partial v}{\partial n}
+                * \f]
+                *
+                * In other words, the present approximation of the horizontal contribution to the turbulent viscosity reduces to:
+                *
+                * \f[
+                * nu_t^h = (c^h h)^2 \sqrt{ 2\left(\frac{\partial u}{\partial n}\right)^2 + 2\left(\frac{\partial v}{\partial n}\right)^2 }
+                * \f]
+                *
+                It should be noted that this simplified approach is formally inconsistent and will result in a turbulent viscosity that is dependent on the grid (orientation).
+                */
                 using std::sqrt;
-                return sqrt(averageBottomShearStress);
-            }();
-
-            const auto turbViscosityV = turbConstV * (kappa/6.0) * ustar * averageDepth;
-
-            /** The horizontal (Smagorinsky-like) contribution to the turbulent viscosity scales with the water depth (squared)
-            * and the magnitude of the stress (rate-of-strain) tensor:
-            *
-            * \f[
-            * nu_t^h = (c^h h)^2 \sqrt{ 2\left(\frac{\partial u}{\partial x}\right)^2 + \left(\frac{\partial u}{\partial y} + \frac{\partial v}{\partial x}\right)^2 + 2\left(\frac{\partial v}{\partial y}\right)^2 }
-            * \f]
-            *
-            * However, based on the velocity vectors in the direct neighbours of the volume face, it is not possible to compute all components of the stress tensor.
-            * Only the gradients of u and v in the direction of the vector between the cell centres is available.
-            * To avoid the reconstruction of the full velocity gradient tensor based on a larger stencil,
-            * the horizontal contribution to the eddy viscosity (in the mixing-length model) is computed using only the velocity gradients normal to the face:
-            *
-            * \f[
-            * \frac{\partial u}{\partial n} , \frac{\partial v}{\partial n}
-            * \f]
-            *
-            * In other words, the present approximation of the horizontal contribution to the turbulent viscosity reduces to:
-            *
-            * \f[
-            * nu_t^h = (c^h h)^2 \sqrt{ 2\left(\frac{\partial u}{\partial n}\right)^2 + 2\left(\frac{\partial v}{\partial n}\right)^2 }
-            * \f]
-            *
-            It should be noted that this simplified approach is formally inconsistent and will result in a turbulent viscosity that is dependent on the grid (orientation).
-            */
-            using std::sqrt;
-            const auto mixingLengthSquared = turbConstH * turbConstH * averageDepth * averageDepth;
-            const auto turbViscosityH = mixingLengthSquared * sqrt(2.0*gradU*gradU + 2.0*gradV*gradV);
-
-            // Total turbulent viscosity
-            return turbBGViscosity + sqrt(turbViscosityV*turbViscosityV + turbViscosityH*turbViscosityH);
+                const auto [gradU, gradV] = gradVelocity;
+                const auto mixingLengthSquared = turbConstH * turbConstH * averageDepth * averageDepth;
+                const auto turbViscosityH = mixingLengthSquared * sqrt(2.0*gradU*gradU + 2.0*gradV*gradV);
+
+                // Total turbulent viscosity
+                return turbBGViscosity + sqrt(turbViscosityV*turbViscosityV + turbViscosityH*turbViscosityH);
+            }
         }();
 
         // Compute the viscous momentum fluxes
+        const auto [gradU, gradV] = gradVelocity;
         const auto uViscousFlux = turbViscosity * averageDepth * gradU;
         const auto vViscousFlux = turbViscosity * averageDepth * gradV;
 
diff --git a/test/freeflow/shallowwater/poiseuilleflow/spatialparams.hh b/test/freeflow/shallowwater/poiseuilleflow/spatialparams.hh
index eb35e02a1f3dfef7566f3b49250d379054430ad6..5e858f3ae1f88dfc28e53313f2aebc2cbdf8be8d 100644
--- a/test/freeflow/shallowwater/poiseuilleflow/spatialparams.hh
+++ b/test/freeflow/shallowwater/poiseuilleflow/spatialparams.hh
@@ -28,7 +28,6 @@
 #include <dumux/common/parameters.hh>
 
 #include <dumux/material/spatialparams/fv.hh>
-#include <dumux/material/fluidmatrixinteractions/frictionlaws/frictionlaw.hh>
 
 namespace Dumux {
 
@@ -65,12 +64,6 @@ public:
     Scalar gravity() const
     { return gravity_; }
 
-    const FrictionLaw<VolumeVariables>&
-    frictionLaw(const Element& element, const SubControlVolume& scv) const
-    {
-        DUNE_THROW(Dune::NotImplemented, "No friction law is implemented for this test!");
-    }
-
     //! Define the bed surface
     Scalar bedSurface(const Element& element, const SubControlVolume& scv) const
     {