Relatively recently, Wolfram has created a nice Heat Transfer Tutorial and a Heat Transfer Verification Manual. I model with many codes and I usually start the Verification and Validation manual and build complexity from there. It is always embarrassing to build a complex model and find that your setup does not pass verification.
The Laplace equation is special case of the heat equation so we should be able to use a verified example as a template for a properly constructed model.
For NeumannValue's, if the flux is into the domain, it is positive. If the flux is out of the domain, it is negative.
At the tutorial link, they define a function HeatTransferModel to create operators for a variety of heat transfer cases that I shall reproduce here:
ClearAll[HeatTransferModel] HeatTransferModel[T_, X_List, k_, ρ_, Cp_, Velocity_, Source_] := Module[{V, Q, a = k}, V = If[Velocity === "NoFlow", 0, ρ*Cp*Velocity.Inactive[Grad][T, X]]; Q = If[Source === "NoSource", 0, Source]; If[FreeQ[a, _?VectorQ], a = a*IdentityMatrix[Length[X]]]; If[VectorQ[a], a = DiagonalMatrix[a]]; (*Note the-sign in the operator*) a = PiecewiseExpand[Piecewise[{{-a, True}}]]; Inactive[Div][a.Inactive[Grad][T, X], X] + V - Q]
If we follow the recipe of tutorial, we should be able to construct and solve a PDE system free of sign errors as I show in the following workflow.
(* Create a Domain *) Ω2D = Rectangle[{2, 2}, {3, 3}]; (* Create parametric PDE operator *) pop = HeatTransferModel[y[x1, x2], {x1, x2}, k, ρ, Cp, "NoFlow", "NoSource"]; (* Replace k parameter *) op = pop /. {k -> 1}; (* Setup flux conditions *) nv2 = NeumannValue[-1, x1 == 2]; nv3 = NeumannValue[1, x1 == 3]; (* Setup Dirichlet Conditions *) dc2 = DirichletCondition[y[x1, x2] == 2 + x1, x2 == 2]; dc3 = DirichletCondition[y[x1, x2] == 3 + x1, x2 == 3]; (* Create PDE system *) pde = {op == nv2 + nv3, dc2, dc3}; (* Solve and Plot *) yfun = NDSolveValue[pde, y, {x1, x2} ∈ Ω2D] Plot3D[Evaluate[yfun[x1, x2]], {x1, x2} ∈ Ω2D, PlotRange -> All, AxesLabel -> {"x1", "x2", "y[x1,x2]"}, BaseStyle -> 12]

You can test that the solution matches that exact solution over the entire range:
Manipulate[ Plot[{x1 + x2, yfun[x1, x2]}, {x1, 2, 3}, PlotRange -> All, AxesLabel -> {"x1", "y[x1,x2]"}, BaseStyle -> 12, PlotStyle -> {Red, Directive[Green, Opacity[0.75], Thickness[0.015], Dashed]}], {x2, 2, 3}, ControlPlacement -> Top]

The exact solution is y=x1+x2Are you sure about this? How does this solution satisfy the Neumann boundary conditions? $\endgroup$x1-direction is1and the sign flops stems from the fact that Neumann conditions are phrased in terms of outward normals... No? $\endgroup$NeumannValuerequires one to do integration by parts and one has to be careful about the signs. Try switching the sign of the Laplacian topde = -Laplacian[y[x1, x2], {x1, x2}];. Then it should work. $\endgroup$NeumannValue[-1, x1 == 2]different from saying that $\frac{\partial y}{\partial x_1}$ evaluated at $x_1=2$ is $-1$? And since the claim is that the solution is $y=x_1+x_2$ then $\frac{\partial y}{\partial x_1}=1$ this is evaluated at $x=2$ is $1$ and not $-1$?. How do you translateNeumannValue[-1, x1 == 2]to normal derivative then? I just did direct translation. May be we need a whole new topic on this. On top of all of this, movingNeumannValuefrom RHS to LHS changes the solution. I never likedNeumannValueand prefer to use normal derivatives... $\endgroup$NeumannValueis a bit counter intuitive, but it makes perfect sense in regard of the weak formulation that is used in FEM. $\endgroup$