Search code examples
neo4jjava-8cypherconsumerjqassistant

JQassistant rule for TestMethods with lambda expressions and consumers asserts


Our project has few Unit Tests in which the asserts are passed as a lambda or consumer to the test class. Example as below. How to write a cypher rule constraint such the asserts are identified and the method is not flagged as without assert. Currently using junit4:TestMethodWithoutAssertion

Test Method :

     @Test 
     public void testSuccessfulIdempotency(){
     transportConsumerFlow.accept(Mockito.mock(TransRequest.class), 
     (t)->{
           assertEquals(t, expectedResponseMessage);
      });
     }

In the sample above, the assert is actually present and valid. But the concept junit4:AssertMethod could not detected may be because it is present as a consumer instead of a direct invocation in Test method.


Solution

  • Lambda expressions are currently not explicitly support by jQAssistant but you may identify them as synthetic static methods (as generated by the bytecode) using the following concept:

    MATCH
      (type:Type)-[:DECLARES]->(lambda:Method)
    WHERE
      exists(lambda.synthetic)
      and exists(lambda.static)
      and lambda.name starts with("lambda$")
    SET
      lambda:Lambda
    WITH
      type, lambda
    MATCH
      (type)-[:DECLARES]->(method:Method)
    WHERE
      method <> lambda
      and method.firstLineNumber <= lambda.firstLineNumber
      and method.lastLineNumber >= lambda.lastLineNumber
    MERGE
      (method)-[:DECLARES_LAMBDA]->(lambda)
    RETURN
      method, collect(lambda)
    

    You'll not see any INVOKES relations from the test methods to the lambda methods, so a custom constraint with the following cypher query needs to be used (based on junit4:TestMethodWithoutAssertion):

    MATCH
      (testType:Type)-[:DECLARES]->(testMethod:Test:Method)
    WHERE
      NOT (testMethod)-[:INVOKES|DECLARES_LAMBDA*..3]->(:Method:Assert)
    RETURN
      testType AS DeclaringType,
      testMethod AS Method