Unit test code with Java 8 Lambdas











up vote
13
down vote

favorite
1












I have been using Java 8 for some months, and I have started to use Lambda expressions, which are very convenient for some cases. However, I often come across some problems to unit test the code that uses a Lambda.



Take as an example the following pseudo-code:



private Bar bar;

public void method(int foo){
bar.useLambda(baz -> baz.setFoo(foo));
}


One approach would be to just verify the call on bar



verify(bar).useLambda(Matchers.<Consumer<Baz>>.any());


But, by doing that, I don't test Lambda's code.



Also note that I am not able to replace the Lambda with a method and use method reference:



bar.useLambda(This::setFooOnBaz);


Because I will not have the foo on that method. Or at least that is what I think.



Have you had this problem before? How can I test or refactor my code to test it properly?





Edit



Since what I am coding is an unit test, I don't want to instantiate bar, and I will be using a mock instead. So I will not be able to just verify the baz.setFoo call.










share|improve this question




























    up vote
    13
    down vote

    favorite
    1












    I have been using Java 8 for some months, and I have started to use Lambda expressions, which are very convenient for some cases. However, I often come across some problems to unit test the code that uses a Lambda.



    Take as an example the following pseudo-code:



    private Bar bar;

    public void method(int foo){
    bar.useLambda(baz -> baz.setFoo(foo));
    }


    One approach would be to just verify the call on bar



    verify(bar).useLambda(Matchers.<Consumer<Baz>>.any());


    But, by doing that, I don't test Lambda's code.



    Also note that I am not able to replace the Lambda with a method and use method reference:



    bar.useLambda(This::setFooOnBaz);


    Because I will not have the foo on that method. Or at least that is what I think.



    Have you had this problem before? How can I test or refactor my code to test it properly?





    Edit



    Since what I am coding is an unit test, I don't want to instantiate bar, and I will be using a mock instead. So I will not be able to just verify the baz.setFoo call.










    share|improve this question


























      up vote
      13
      down vote

      favorite
      1









      up vote
      13
      down vote

      favorite
      1






      1





      I have been using Java 8 for some months, and I have started to use Lambda expressions, which are very convenient for some cases. However, I often come across some problems to unit test the code that uses a Lambda.



      Take as an example the following pseudo-code:



      private Bar bar;

      public void method(int foo){
      bar.useLambda(baz -> baz.setFoo(foo));
      }


      One approach would be to just verify the call on bar



      verify(bar).useLambda(Matchers.<Consumer<Baz>>.any());


      But, by doing that, I don't test Lambda's code.



      Also note that I am not able to replace the Lambda with a method and use method reference:



      bar.useLambda(This::setFooOnBaz);


      Because I will not have the foo on that method. Or at least that is what I think.



      Have you had this problem before? How can I test or refactor my code to test it properly?





      Edit



      Since what I am coding is an unit test, I don't want to instantiate bar, and I will be using a mock instead. So I will not be able to just verify the baz.setFoo call.










      share|improve this question















      I have been using Java 8 for some months, and I have started to use Lambda expressions, which are very convenient for some cases. However, I often come across some problems to unit test the code that uses a Lambda.



      Take as an example the following pseudo-code:



      private Bar bar;

      public void method(int foo){
      bar.useLambda(baz -> baz.setFoo(foo));
      }


      One approach would be to just verify the call on bar



      verify(bar).useLambda(Matchers.<Consumer<Baz>>.any());


      But, by doing that, I don't test Lambda's code.



      Also note that I am not able to replace the Lambda with a method and use method reference:



      bar.useLambda(This::setFooOnBaz);


      Because I will not have the foo on that method. Or at least that is what I think.



      Have you had this problem before? How can I test or refactor my code to test it properly?





      Edit



      Since what I am coding is an unit test, I don't want to instantiate bar, and I will be using a mock instead. So I will not be able to just verify the baz.setFoo call.







      java unit-testing lambda java-8






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Feb 24 '15 at 4:37

























      asked Feb 24 '15 at 4:15









      Fdiazreal

      2451411




      2451411
























          4 Answers
          4






          active

          oldest

          votes

















          up vote
          15
          down vote



          accepted










          You can't unit test a lambda directly, since it doesn't have a name. There's no way to call it unless you have a reference to it.



          The usual alternative is to refactor the lambda into a named method and use a method reference from product code and call the method by name from test code. As you note, this case can't be refactored this way because it captures foo, and the only thing that can be captured by a method reference is the receiver.



          But the answer from yshavit touches upon an important point about whether it's necessary to unit test private methods. A lambda can certainly be considered a private method.



          There's a larger point here too. One of the priciples of unit testing is that you don't need to unit test anything that's too simple to break. This aligns well with the ideal case for lambda, which is an expression that's so simple it's obviously correct. (At least, that's what I consider ideal.) Consider the example:



              baz -> baz.setFoo(foo)


          Is there any doubt that this lambda expression, when handed a Baz reference, will call its setFoo method and pass it foo as an argument? Maybe it's so simple that it doesn't need to be unit tested.



          On the other hand, this is merely an example, and maybe the actual lambda you want to test is considerably more complicated. I've seen code that uses large, nested, multi-line lambdas. See this answer and its question and other answers, for example. Such lambdas are indeed difficult to debug and test. If the code in the lambda is complex enough that it warrants testing, maybe that code ought to be refactored out of the lambda, so that it can be tested using the usual techniques.






          share|improve this answer























          • Your were right when you've said that my actual lambda is a little more complicated than a set, but it is still simple enough to consider that it will not break . After all, maybe I am just trying to unit test 100% of the code, and that is the root problem. Thanks!
            – Fdiazreal
            Feb 24 '15 at 10:55










          • I disagree that something is “too simple to break”. Some of the toughest bugs to find are “simple” code that doesn’t do what you think it does, or maybe not all the time. Anything can break, especially by not changing when it should to align with another aspect of a change.
            – Bohemian
            Nov 11 at 2:59




















          up vote
          11
          down vote













          Treat the lambdas like you would a private method; don't test it separately, but rather test the effect it has. In your case, invoking method(foo) should cause bar.setFoo to happen -- so, call method(foo) and then verify bar.getFoo().






          share|improve this answer

















          • 1




            Agreed, don't unit test the lambda; unit test the outcome.
            – whitfin
            Feb 24 '15 at 4:21










          • How would you verify baz.setFoo without instantiating bar, hence, using bar as a mock?
            – Fdiazreal
            Feb 24 '15 at 4:26








          • 3




            @Fdiazreal: as you code is delegating to Bar, there is no point in testing this action “without instantiating bar”. Of course, you can test baz.setFoo(foo) on its own as well. Since setFoo is an ordinary method, you should have no problems testing it— simply forget about the lambda.
            – Holger
            Feb 24 '15 at 8:47


















          up vote
          0
          down vote













          My team recently had a similar issue, and we found a solution that works nicely with jMock. Perhaps something similar would work for whatever mocking library you're using.



          Let's assume the Bar interface mentioned in your example looks like this:



          interface Bar {
          void useLambda(BazRunnable lambda);
          Bam useLambdaForResult(BazCallable<Bam> lambda);
          }

          interface BazRunnable {
          void run(Baz baz);
          }

          interface BazCallable<T> {
          T call(Baz baz);
          }


          We create custom jMock Actions for executing BazRunnables and BazCallables:



          class BazRunnableAction implements Action {

          private final Baz baz;

          BazRunnableAction(Baz baz) {
          this.baz = baz;
          }

          @Override
          public Object invoke(Invocation invocation) {
          BazRunnable task = (BazRunnable) invocation.getParameter(0);
          task.run(baz);
          return null;
          }

          @Override
          public void describeTo(Description description) {
          // Etc
          }
          }

          class BazCallableAction implements Action {

          private final Baz baz;

          BazCallableAction(Baz baz) {
          this.baz = baz;
          }

          @Override
          public Object invoke(Invocation invocation) {
          BazCallable task = (BazCallable) invocation.getParameter(0);
          return task.call(baz);
          }

          @Override
          public void describeTo(Description description) {
          // Etc
          }
          }


          Now we can use the custom actions to test interactions with mocked dependencies that happen within lambdas. To test the method void method(int foo) from your example we'd do this:



          Mockery context = new Mockery();
          int foo = 1234;
          Bar bar = context.mock(Bar.class);
          Baz baz = context.mock(Baz.class);

          context.checking(new Expectations() {{
          oneOf(bar).useLambda(with(any(BazRunnable.class)));
          will(new BazRunnableAction(baz));
          oneOf(baz).setFoo(foo);
          }});

          UnitBeingTested unit = new UnitBeingTested(bar);
          unit.method(foo);

          context.assertIsSatisfied();


          We can save some boilerplate by adding convenience methods to the Expectations class:



          class BazExpectations extends Expectations {

          protected BazRunnable withBazRunnable(Baz baz) {
          addParameterMatcher(any(BazRunnable.class));
          currentBuilder().setAction(new BazRunnableAction(baz));
          return null;
          }

          protected <T> BazCallable<T> withBazCallable(Baz baz) {
          addParameterMatcher(any(BazCallable.class));
          currentBuilder().setAction(new BazCallableAction(baz));
          return null;
          }
          }


          This makes the test expectations a little clearer:



          context.checking(new BazExpectations() {{
          oneOf(bar).useLambda(withBazRunnable(baz));
          oneOf(baz).setFoo(foo);
          }});





          share|improve this answer




























            up vote
            0
            down vote













            My usual approach is to use an ArgumentCaptor. This way you could capture reference to actual lambda function that was passed and could validate its behavior separately.



            Assuming your Lambda is reference to MyFunctionalInterface, I would do something like.



            ArgumentCaptor<MyFunctionalInterface> lambdaCaptor = ArgumentCaptor.forClass(MyFunctionalInterface.class);

            verify(bar).useLambda(lambdaCaptor.capture());

            // Not retrieve captured arg (which is reference to lamdba).
            MyFuntionalRef usedLambda = lambdaCaptor.getValue();

            // Now you have reference to actual lambda that was passed, validate its behavior.
            verifyMyLambdaBehavior(usedLambda);





            share|improve this answer





















              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














               

              draft saved


              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f28688047%2funit-test-code-with-java-8-lambdas%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              4 Answers
              4






              active

              oldest

              votes








              4 Answers
              4






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              15
              down vote



              accepted










              You can't unit test a lambda directly, since it doesn't have a name. There's no way to call it unless you have a reference to it.



              The usual alternative is to refactor the lambda into a named method and use a method reference from product code and call the method by name from test code. As you note, this case can't be refactored this way because it captures foo, and the only thing that can be captured by a method reference is the receiver.



              But the answer from yshavit touches upon an important point about whether it's necessary to unit test private methods. A lambda can certainly be considered a private method.



              There's a larger point here too. One of the priciples of unit testing is that you don't need to unit test anything that's too simple to break. This aligns well with the ideal case for lambda, which is an expression that's so simple it's obviously correct. (At least, that's what I consider ideal.) Consider the example:



                  baz -> baz.setFoo(foo)


              Is there any doubt that this lambda expression, when handed a Baz reference, will call its setFoo method and pass it foo as an argument? Maybe it's so simple that it doesn't need to be unit tested.



              On the other hand, this is merely an example, and maybe the actual lambda you want to test is considerably more complicated. I've seen code that uses large, nested, multi-line lambdas. See this answer and its question and other answers, for example. Such lambdas are indeed difficult to debug and test. If the code in the lambda is complex enough that it warrants testing, maybe that code ought to be refactored out of the lambda, so that it can be tested using the usual techniques.






              share|improve this answer























              • Your were right when you've said that my actual lambda is a little more complicated than a set, but it is still simple enough to consider that it will not break . After all, maybe I am just trying to unit test 100% of the code, and that is the root problem. Thanks!
                – Fdiazreal
                Feb 24 '15 at 10:55










              • I disagree that something is “too simple to break”. Some of the toughest bugs to find are “simple” code that doesn’t do what you think it does, or maybe not all the time. Anything can break, especially by not changing when it should to align with another aspect of a change.
                – Bohemian
                Nov 11 at 2:59

















              up vote
              15
              down vote



              accepted










              You can't unit test a lambda directly, since it doesn't have a name. There's no way to call it unless you have a reference to it.



              The usual alternative is to refactor the lambda into a named method and use a method reference from product code and call the method by name from test code. As you note, this case can't be refactored this way because it captures foo, and the only thing that can be captured by a method reference is the receiver.



              But the answer from yshavit touches upon an important point about whether it's necessary to unit test private methods. A lambda can certainly be considered a private method.



              There's a larger point here too. One of the priciples of unit testing is that you don't need to unit test anything that's too simple to break. This aligns well with the ideal case for lambda, which is an expression that's so simple it's obviously correct. (At least, that's what I consider ideal.) Consider the example:



                  baz -> baz.setFoo(foo)


              Is there any doubt that this lambda expression, when handed a Baz reference, will call its setFoo method and pass it foo as an argument? Maybe it's so simple that it doesn't need to be unit tested.



              On the other hand, this is merely an example, and maybe the actual lambda you want to test is considerably more complicated. I've seen code that uses large, nested, multi-line lambdas. See this answer and its question and other answers, for example. Such lambdas are indeed difficult to debug and test. If the code in the lambda is complex enough that it warrants testing, maybe that code ought to be refactored out of the lambda, so that it can be tested using the usual techniques.






              share|improve this answer























              • Your were right when you've said that my actual lambda is a little more complicated than a set, but it is still simple enough to consider that it will not break . After all, maybe I am just trying to unit test 100% of the code, and that is the root problem. Thanks!
                – Fdiazreal
                Feb 24 '15 at 10:55










              • I disagree that something is “too simple to break”. Some of the toughest bugs to find are “simple” code that doesn’t do what you think it does, or maybe not all the time. Anything can break, especially by not changing when it should to align with another aspect of a change.
                – Bohemian
                Nov 11 at 2:59















              up vote
              15
              down vote



              accepted







              up vote
              15
              down vote



              accepted






              You can't unit test a lambda directly, since it doesn't have a name. There's no way to call it unless you have a reference to it.



              The usual alternative is to refactor the lambda into a named method and use a method reference from product code and call the method by name from test code. As you note, this case can't be refactored this way because it captures foo, and the only thing that can be captured by a method reference is the receiver.



              But the answer from yshavit touches upon an important point about whether it's necessary to unit test private methods. A lambda can certainly be considered a private method.



              There's a larger point here too. One of the priciples of unit testing is that you don't need to unit test anything that's too simple to break. This aligns well with the ideal case for lambda, which is an expression that's so simple it's obviously correct. (At least, that's what I consider ideal.) Consider the example:



                  baz -> baz.setFoo(foo)


              Is there any doubt that this lambda expression, when handed a Baz reference, will call its setFoo method and pass it foo as an argument? Maybe it's so simple that it doesn't need to be unit tested.



              On the other hand, this is merely an example, and maybe the actual lambda you want to test is considerably more complicated. I've seen code that uses large, nested, multi-line lambdas. See this answer and its question and other answers, for example. Such lambdas are indeed difficult to debug and test. If the code in the lambda is complex enough that it warrants testing, maybe that code ought to be refactored out of the lambda, so that it can be tested using the usual techniques.






              share|improve this answer














              You can't unit test a lambda directly, since it doesn't have a name. There's no way to call it unless you have a reference to it.



              The usual alternative is to refactor the lambda into a named method and use a method reference from product code and call the method by name from test code. As you note, this case can't be refactored this way because it captures foo, and the only thing that can be captured by a method reference is the receiver.



              But the answer from yshavit touches upon an important point about whether it's necessary to unit test private methods. A lambda can certainly be considered a private method.



              There's a larger point here too. One of the priciples of unit testing is that you don't need to unit test anything that's too simple to break. This aligns well with the ideal case for lambda, which is an expression that's so simple it's obviously correct. (At least, that's what I consider ideal.) Consider the example:



                  baz -> baz.setFoo(foo)


              Is there any doubt that this lambda expression, when handed a Baz reference, will call its setFoo method and pass it foo as an argument? Maybe it's so simple that it doesn't need to be unit tested.



              On the other hand, this is merely an example, and maybe the actual lambda you want to test is considerably more complicated. I've seen code that uses large, nested, multi-line lambdas. See this answer and its question and other answers, for example. Such lambdas are indeed difficult to debug and test. If the code in the lambda is complex enough that it warrants testing, maybe that code ought to be refactored out of the lambda, so that it can be tested using the usual techniques.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Nov 11 at 18:13

























              answered Feb 24 '15 at 6:48









              Stuart Marks

              77.7k24133202




              77.7k24133202












              • Your were right when you've said that my actual lambda is a little more complicated than a set, but it is still simple enough to consider that it will not break . After all, maybe I am just trying to unit test 100% of the code, and that is the root problem. Thanks!
                – Fdiazreal
                Feb 24 '15 at 10:55










              • I disagree that something is “too simple to break”. Some of the toughest bugs to find are “simple” code that doesn’t do what you think it does, or maybe not all the time. Anything can break, especially by not changing when it should to align with another aspect of a change.
                – Bohemian
                Nov 11 at 2:59




















              • Your were right when you've said that my actual lambda is a little more complicated than a set, but it is still simple enough to consider that it will not break . After all, maybe I am just trying to unit test 100% of the code, and that is the root problem. Thanks!
                – Fdiazreal
                Feb 24 '15 at 10:55










              • I disagree that something is “too simple to break”. Some of the toughest bugs to find are “simple” code that doesn’t do what you think it does, or maybe not all the time. Anything can break, especially by not changing when it should to align with another aspect of a change.
                – Bohemian
                Nov 11 at 2:59


















              Your were right when you've said that my actual lambda is a little more complicated than a set, but it is still simple enough to consider that it will not break . After all, maybe I am just trying to unit test 100% of the code, and that is the root problem. Thanks!
              – Fdiazreal
              Feb 24 '15 at 10:55




              Your were right when you've said that my actual lambda is a little more complicated than a set, but it is still simple enough to consider that it will not break . After all, maybe I am just trying to unit test 100% of the code, and that is the root problem. Thanks!
              – Fdiazreal
              Feb 24 '15 at 10:55












              I disagree that something is “too simple to break”. Some of the toughest bugs to find are “simple” code that doesn’t do what you think it does, or maybe not all the time. Anything can break, especially by not changing when it should to align with another aspect of a change.
              – Bohemian
              Nov 11 at 2:59






              I disagree that something is “too simple to break”. Some of the toughest bugs to find are “simple” code that doesn’t do what you think it does, or maybe not all the time. Anything can break, especially by not changing when it should to align with another aspect of a change.
              – Bohemian
              Nov 11 at 2:59














              up vote
              11
              down vote













              Treat the lambdas like you would a private method; don't test it separately, but rather test the effect it has. In your case, invoking method(foo) should cause bar.setFoo to happen -- so, call method(foo) and then verify bar.getFoo().






              share|improve this answer

















              • 1




                Agreed, don't unit test the lambda; unit test the outcome.
                – whitfin
                Feb 24 '15 at 4:21










              • How would you verify baz.setFoo without instantiating bar, hence, using bar as a mock?
                – Fdiazreal
                Feb 24 '15 at 4:26








              • 3




                @Fdiazreal: as you code is delegating to Bar, there is no point in testing this action “without instantiating bar”. Of course, you can test baz.setFoo(foo) on its own as well. Since setFoo is an ordinary method, you should have no problems testing it— simply forget about the lambda.
                – Holger
                Feb 24 '15 at 8:47















              up vote
              11
              down vote













              Treat the lambdas like you would a private method; don't test it separately, but rather test the effect it has. In your case, invoking method(foo) should cause bar.setFoo to happen -- so, call method(foo) and then verify bar.getFoo().






              share|improve this answer

















              • 1




                Agreed, don't unit test the lambda; unit test the outcome.
                – whitfin
                Feb 24 '15 at 4:21










              • How would you verify baz.setFoo without instantiating bar, hence, using bar as a mock?
                – Fdiazreal
                Feb 24 '15 at 4:26








              • 3




                @Fdiazreal: as you code is delegating to Bar, there is no point in testing this action “without instantiating bar”. Of course, you can test baz.setFoo(foo) on its own as well. Since setFoo is an ordinary method, you should have no problems testing it— simply forget about the lambda.
                – Holger
                Feb 24 '15 at 8:47













              up vote
              11
              down vote










              up vote
              11
              down vote









              Treat the lambdas like you would a private method; don't test it separately, but rather test the effect it has. In your case, invoking method(foo) should cause bar.setFoo to happen -- so, call method(foo) and then verify bar.getFoo().






              share|improve this answer












              Treat the lambdas like you would a private method; don't test it separately, but rather test the effect it has. In your case, invoking method(foo) should cause bar.setFoo to happen -- so, call method(foo) and then verify bar.getFoo().







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Feb 24 '15 at 4:19









              yshavit

              34.6k66195




              34.6k66195








              • 1




                Agreed, don't unit test the lambda; unit test the outcome.
                – whitfin
                Feb 24 '15 at 4:21










              • How would you verify baz.setFoo without instantiating bar, hence, using bar as a mock?
                – Fdiazreal
                Feb 24 '15 at 4:26








              • 3




                @Fdiazreal: as you code is delegating to Bar, there is no point in testing this action “without instantiating bar”. Of course, you can test baz.setFoo(foo) on its own as well. Since setFoo is an ordinary method, you should have no problems testing it— simply forget about the lambda.
                – Holger
                Feb 24 '15 at 8:47














              • 1




                Agreed, don't unit test the lambda; unit test the outcome.
                – whitfin
                Feb 24 '15 at 4:21










              • How would you verify baz.setFoo without instantiating bar, hence, using bar as a mock?
                – Fdiazreal
                Feb 24 '15 at 4:26








              • 3




                @Fdiazreal: as you code is delegating to Bar, there is no point in testing this action “without instantiating bar”. Of course, you can test baz.setFoo(foo) on its own as well. Since setFoo is an ordinary method, you should have no problems testing it— simply forget about the lambda.
                – Holger
                Feb 24 '15 at 8:47








              1




              1




              Agreed, don't unit test the lambda; unit test the outcome.
              – whitfin
              Feb 24 '15 at 4:21




              Agreed, don't unit test the lambda; unit test the outcome.
              – whitfin
              Feb 24 '15 at 4:21












              How would you verify baz.setFoo without instantiating bar, hence, using bar as a mock?
              – Fdiazreal
              Feb 24 '15 at 4:26






              How would you verify baz.setFoo without instantiating bar, hence, using bar as a mock?
              – Fdiazreal
              Feb 24 '15 at 4:26






              3




              3




              @Fdiazreal: as you code is delegating to Bar, there is no point in testing this action “without instantiating bar”. Of course, you can test baz.setFoo(foo) on its own as well. Since setFoo is an ordinary method, you should have no problems testing it— simply forget about the lambda.
              – Holger
              Feb 24 '15 at 8:47




              @Fdiazreal: as you code is delegating to Bar, there is no point in testing this action “without instantiating bar”. Of course, you can test baz.setFoo(foo) on its own as well. Since setFoo is an ordinary method, you should have no problems testing it— simply forget about the lambda.
              – Holger
              Feb 24 '15 at 8:47










              up vote
              0
              down vote













              My team recently had a similar issue, and we found a solution that works nicely with jMock. Perhaps something similar would work for whatever mocking library you're using.



              Let's assume the Bar interface mentioned in your example looks like this:



              interface Bar {
              void useLambda(BazRunnable lambda);
              Bam useLambdaForResult(BazCallable<Bam> lambda);
              }

              interface BazRunnable {
              void run(Baz baz);
              }

              interface BazCallable<T> {
              T call(Baz baz);
              }


              We create custom jMock Actions for executing BazRunnables and BazCallables:



              class BazRunnableAction implements Action {

              private final Baz baz;

              BazRunnableAction(Baz baz) {
              this.baz = baz;
              }

              @Override
              public Object invoke(Invocation invocation) {
              BazRunnable task = (BazRunnable) invocation.getParameter(0);
              task.run(baz);
              return null;
              }

              @Override
              public void describeTo(Description description) {
              // Etc
              }
              }

              class BazCallableAction implements Action {

              private final Baz baz;

              BazCallableAction(Baz baz) {
              this.baz = baz;
              }

              @Override
              public Object invoke(Invocation invocation) {
              BazCallable task = (BazCallable) invocation.getParameter(0);
              return task.call(baz);
              }

              @Override
              public void describeTo(Description description) {
              // Etc
              }
              }


              Now we can use the custom actions to test interactions with mocked dependencies that happen within lambdas. To test the method void method(int foo) from your example we'd do this:



              Mockery context = new Mockery();
              int foo = 1234;
              Bar bar = context.mock(Bar.class);
              Baz baz = context.mock(Baz.class);

              context.checking(new Expectations() {{
              oneOf(bar).useLambda(with(any(BazRunnable.class)));
              will(new BazRunnableAction(baz));
              oneOf(baz).setFoo(foo);
              }});

              UnitBeingTested unit = new UnitBeingTested(bar);
              unit.method(foo);

              context.assertIsSatisfied();


              We can save some boilerplate by adding convenience methods to the Expectations class:



              class BazExpectations extends Expectations {

              protected BazRunnable withBazRunnable(Baz baz) {
              addParameterMatcher(any(BazRunnable.class));
              currentBuilder().setAction(new BazRunnableAction(baz));
              return null;
              }

              protected <T> BazCallable<T> withBazCallable(Baz baz) {
              addParameterMatcher(any(BazCallable.class));
              currentBuilder().setAction(new BazCallableAction(baz));
              return null;
              }
              }


              This makes the test expectations a little clearer:



              context.checking(new BazExpectations() {{
              oneOf(bar).useLambda(withBazRunnable(baz));
              oneOf(baz).setFoo(foo);
              }});





              share|improve this answer

























                up vote
                0
                down vote













                My team recently had a similar issue, and we found a solution that works nicely with jMock. Perhaps something similar would work for whatever mocking library you're using.



                Let's assume the Bar interface mentioned in your example looks like this:



                interface Bar {
                void useLambda(BazRunnable lambda);
                Bam useLambdaForResult(BazCallable<Bam> lambda);
                }

                interface BazRunnable {
                void run(Baz baz);
                }

                interface BazCallable<T> {
                T call(Baz baz);
                }


                We create custom jMock Actions for executing BazRunnables and BazCallables:



                class BazRunnableAction implements Action {

                private final Baz baz;

                BazRunnableAction(Baz baz) {
                this.baz = baz;
                }

                @Override
                public Object invoke(Invocation invocation) {
                BazRunnable task = (BazRunnable) invocation.getParameter(0);
                task.run(baz);
                return null;
                }

                @Override
                public void describeTo(Description description) {
                // Etc
                }
                }

                class BazCallableAction implements Action {

                private final Baz baz;

                BazCallableAction(Baz baz) {
                this.baz = baz;
                }

                @Override
                public Object invoke(Invocation invocation) {
                BazCallable task = (BazCallable) invocation.getParameter(0);
                return task.call(baz);
                }

                @Override
                public void describeTo(Description description) {
                // Etc
                }
                }


                Now we can use the custom actions to test interactions with mocked dependencies that happen within lambdas. To test the method void method(int foo) from your example we'd do this:



                Mockery context = new Mockery();
                int foo = 1234;
                Bar bar = context.mock(Bar.class);
                Baz baz = context.mock(Baz.class);

                context.checking(new Expectations() {{
                oneOf(bar).useLambda(with(any(BazRunnable.class)));
                will(new BazRunnableAction(baz));
                oneOf(baz).setFoo(foo);
                }});

                UnitBeingTested unit = new UnitBeingTested(bar);
                unit.method(foo);

                context.assertIsSatisfied();


                We can save some boilerplate by adding convenience methods to the Expectations class:



                class BazExpectations extends Expectations {

                protected BazRunnable withBazRunnable(Baz baz) {
                addParameterMatcher(any(BazRunnable.class));
                currentBuilder().setAction(new BazRunnableAction(baz));
                return null;
                }

                protected <T> BazCallable<T> withBazCallable(Baz baz) {
                addParameterMatcher(any(BazCallable.class));
                currentBuilder().setAction(new BazCallableAction(baz));
                return null;
                }
                }


                This makes the test expectations a little clearer:



                context.checking(new BazExpectations() {{
                oneOf(bar).useLambda(withBazRunnable(baz));
                oneOf(baz).setFoo(foo);
                }});





                share|improve this answer























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  My team recently had a similar issue, and we found a solution that works nicely with jMock. Perhaps something similar would work for whatever mocking library you're using.



                  Let's assume the Bar interface mentioned in your example looks like this:



                  interface Bar {
                  void useLambda(BazRunnable lambda);
                  Bam useLambdaForResult(BazCallable<Bam> lambda);
                  }

                  interface BazRunnable {
                  void run(Baz baz);
                  }

                  interface BazCallable<T> {
                  T call(Baz baz);
                  }


                  We create custom jMock Actions for executing BazRunnables and BazCallables:



                  class BazRunnableAction implements Action {

                  private final Baz baz;

                  BazRunnableAction(Baz baz) {
                  this.baz = baz;
                  }

                  @Override
                  public Object invoke(Invocation invocation) {
                  BazRunnable task = (BazRunnable) invocation.getParameter(0);
                  task.run(baz);
                  return null;
                  }

                  @Override
                  public void describeTo(Description description) {
                  // Etc
                  }
                  }

                  class BazCallableAction implements Action {

                  private final Baz baz;

                  BazCallableAction(Baz baz) {
                  this.baz = baz;
                  }

                  @Override
                  public Object invoke(Invocation invocation) {
                  BazCallable task = (BazCallable) invocation.getParameter(0);
                  return task.call(baz);
                  }

                  @Override
                  public void describeTo(Description description) {
                  // Etc
                  }
                  }


                  Now we can use the custom actions to test interactions with mocked dependencies that happen within lambdas. To test the method void method(int foo) from your example we'd do this:



                  Mockery context = new Mockery();
                  int foo = 1234;
                  Bar bar = context.mock(Bar.class);
                  Baz baz = context.mock(Baz.class);

                  context.checking(new Expectations() {{
                  oneOf(bar).useLambda(with(any(BazRunnable.class)));
                  will(new BazRunnableAction(baz));
                  oneOf(baz).setFoo(foo);
                  }});

                  UnitBeingTested unit = new UnitBeingTested(bar);
                  unit.method(foo);

                  context.assertIsSatisfied();


                  We can save some boilerplate by adding convenience methods to the Expectations class:



                  class BazExpectations extends Expectations {

                  protected BazRunnable withBazRunnable(Baz baz) {
                  addParameterMatcher(any(BazRunnable.class));
                  currentBuilder().setAction(new BazRunnableAction(baz));
                  return null;
                  }

                  protected <T> BazCallable<T> withBazCallable(Baz baz) {
                  addParameterMatcher(any(BazCallable.class));
                  currentBuilder().setAction(new BazCallableAction(baz));
                  return null;
                  }
                  }


                  This makes the test expectations a little clearer:



                  context.checking(new BazExpectations() {{
                  oneOf(bar).useLambda(withBazRunnable(baz));
                  oneOf(baz).setFoo(foo);
                  }});





                  share|improve this answer












                  My team recently had a similar issue, and we found a solution that works nicely with jMock. Perhaps something similar would work for whatever mocking library you're using.



                  Let's assume the Bar interface mentioned in your example looks like this:



                  interface Bar {
                  void useLambda(BazRunnable lambda);
                  Bam useLambdaForResult(BazCallable<Bam> lambda);
                  }

                  interface BazRunnable {
                  void run(Baz baz);
                  }

                  interface BazCallable<T> {
                  T call(Baz baz);
                  }


                  We create custom jMock Actions for executing BazRunnables and BazCallables:



                  class BazRunnableAction implements Action {

                  private final Baz baz;

                  BazRunnableAction(Baz baz) {
                  this.baz = baz;
                  }

                  @Override
                  public Object invoke(Invocation invocation) {
                  BazRunnable task = (BazRunnable) invocation.getParameter(0);
                  task.run(baz);
                  return null;
                  }

                  @Override
                  public void describeTo(Description description) {
                  // Etc
                  }
                  }

                  class BazCallableAction implements Action {

                  private final Baz baz;

                  BazCallableAction(Baz baz) {
                  this.baz = baz;
                  }

                  @Override
                  public Object invoke(Invocation invocation) {
                  BazCallable task = (BazCallable) invocation.getParameter(0);
                  return task.call(baz);
                  }

                  @Override
                  public void describeTo(Description description) {
                  // Etc
                  }
                  }


                  Now we can use the custom actions to test interactions with mocked dependencies that happen within lambdas. To test the method void method(int foo) from your example we'd do this:



                  Mockery context = new Mockery();
                  int foo = 1234;
                  Bar bar = context.mock(Bar.class);
                  Baz baz = context.mock(Baz.class);

                  context.checking(new Expectations() {{
                  oneOf(bar).useLambda(with(any(BazRunnable.class)));
                  will(new BazRunnableAction(baz));
                  oneOf(baz).setFoo(foo);
                  }});

                  UnitBeingTested unit = new UnitBeingTested(bar);
                  unit.method(foo);

                  context.assertIsSatisfied();


                  We can save some boilerplate by adding convenience methods to the Expectations class:



                  class BazExpectations extends Expectations {

                  protected BazRunnable withBazRunnable(Baz baz) {
                  addParameterMatcher(any(BazRunnable.class));
                  currentBuilder().setAction(new BazRunnableAction(baz));
                  return null;
                  }

                  protected <T> BazCallable<T> withBazCallable(Baz baz) {
                  addParameterMatcher(any(BazCallable.class));
                  currentBuilder().setAction(new BazCallableAction(baz));
                  return null;
                  }
                  }


                  This makes the test expectations a little clearer:



                  context.checking(new BazExpectations() {{
                  oneOf(bar).useLambda(withBazRunnable(baz));
                  oneOf(baz).setFoo(foo);
                  }});






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Oct 26 at 15:17









                  akwizgran

                  8616




                  8616






















                      up vote
                      0
                      down vote













                      My usual approach is to use an ArgumentCaptor. This way you could capture reference to actual lambda function that was passed and could validate its behavior separately.



                      Assuming your Lambda is reference to MyFunctionalInterface, I would do something like.



                      ArgumentCaptor<MyFunctionalInterface> lambdaCaptor = ArgumentCaptor.forClass(MyFunctionalInterface.class);

                      verify(bar).useLambda(lambdaCaptor.capture());

                      // Not retrieve captured arg (which is reference to lamdba).
                      MyFuntionalRef usedLambda = lambdaCaptor.getValue();

                      // Now you have reference to actual lambda that was passed, validate its behavior.
                      verifyMyLambdaBehavior(usedLambda);





                      share|improve this answer

























                        up vote
                        0
                        down vote













                        My usual approach is to use an ArgumentCaptor. This way you could capture reference to actual lambda function that was passed and could validate its behavior separately.



                        Assuming your Lambda is reference to MyFunctionalInterface, I would do something like.



                        ArgumentCaptor<MyFunctionalInterface> lambdaCaptor = ArgumentCaptor.forClass(MyFunctionalInterface.class);

                        verify(bar).useLambda(lambdaCaptor.capture());

                        // Not retrieve captured arg (which is reference to lamdba).
                        MyFuntionalRef usedLambda = lambdaCaptor.getValue();

                        // Now you have reference to actual lambda that was passed, validate its behavior.
                        verifyMyLambdaBehavior(usedLambda);





                        share|improve this answer























                          up vote
                          0
                          down vote










                          up vote
                          0
                          down vote









                          My usual approach is to use an ArgumentCaptor. This way you could capture reference to actual lambda function that was passed and could validate its behavior separately.



                          Assuming your Lambda is reference to MyFunctionalInterface, I would do something like.



                          ArgumentCaptor<MyFunctionalInterface> lambdaCaptor = ArgumentCaptor.forClass(MyFunctionalInterface.class);

                          verify(bar).useLambda(lambdaCaptor.capture());

                          // Not retrieve captured arg (which is reference to lamdba).
                          MyFuntionalRef usedLambda = lambdaCaptor.getValue();

                          // Now you have reference to actual lambda that was passed, validate its behavior.
                          verifyMyLambdaBehavior(usedLambda);





                          share|improve this answer












                          My usual approach is to use an ArgumentCaptor. This way you could capture reference to actual lambda function that was passed and could validate its behavior separately.



                          Assuming your Lambda is reference to MyFunctionalInterface, I would do something like.



                          ArgumentCaptor<MyFunctionalInterface> lambdaCaptor = ArgumentCaptor.forClass(MyFunctionalInterface.class);

                          verify(bar).useLambda(lambdaCaptor.capture());

                          // Not retrieve captured arg (which is reference to lamdba).
                          MyFuntionalRef usedLambda = lambdaCaptor.getValue();

                          // Now you have reference to actual lambda that was passed, validate its behavior.
                          verifyMyLambdaBehavior(usedLambda);






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 11 at 2:54









                          Microkernel

                          69431233




                          69431233






























                               

                              draft saved


                              draft discarded



















































                               


                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f28688047%2funit-test-code-with-java-8-lambdas%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Bressuire

                              Vorschmack

                              Quarantine