Search code examples
javaodataolingo

Writing Integration Test of ExpressionVisitor with Olingo / ODATA 4


I'm implementing a web service respecting version 4 of the OData standard in Java language with the framework Olingo. I need to customize the response of $filter. I've implemented a Visitor as documented in the quick start. I need to implement an integration Test to try a different kind of grammar and to prevent regression bug in case of future maintenance.

For the V2, I found the following tutorial and the following code :

@Test
public void printExpressionWithProperty() throws Exception {
  //Use a mocked edmProvider for this tutorial
  TestEdmProvider provider = new TestEdmProvider();
  Edm edm = RuntimeDelegate.createEdm(provider);
  EdmEntityType entityType = edm.getEntityType(TestEdmProvider.NAMESPACE_1, TestEdmProvider.ENTITY_TYPE_1_1.getName());

  String rawExpression = "EmployeeId eq '1'";
  FilterExpression expression = UriParser.parseFilter (null, entityType, rawExpression);
  String whereClause = (String) expression.accept(new JdbcSimpleStringVisitor());
  System.out.println("Raw: " + rawExpression + " ------> Whereclause: " + whereClause);
  System.out.println();
}

Unfortunately, UriParser.parseFilter doesn't exist in the v4.

I tried this :

public class MyVisitorTest {

    private final FullQualifiedName NAME1 = new FullQualifiedName("testNamespace1", "myfield");
    private final OData odata = OData.newInstance();

    public EdmEntityType createEntityType(final FullQualifiedName fqn) {
        if (NAME1.equals(fqn)) {
            EdmEntityType entityType = mock(EdmEntityType.class);
            when(entityType.getNamespace()).thenReturn(fqn.getNamespace());
            when(entityType.getName()).thenReturn(fqn.getName());
            return entityType;
        }
        return null;
    }


    private Expression parseExpression(final String expressionString)
            throws UriParserException, UriValidationException {

        UriTokenizer tokenizer = new UriTokenizer(expressionString);

        EdmEntityType entityType = createEntityType(NAME1);

        Edm edm = mock(Edm.class);
        when(edm.getEntityType(NAME1)).thenReturn(entityType);

        final Expression expression = new ExpressionParser(edm, odata).parse(tokenizer, null, null, null);
        assertNotNull(expression);
        assertTrue(tokenizer.next(UriTokenizer.TokenKind.EOF));
        return expression;
    }

    @Test
    public void simpleTest() throws UriParserException, UriValidationException, ODataApplicationException, ExpressionVisitException {

        String exp = "myfield gt 2019-01-01T00:00:00Z";
        Expression e = parseExpression(exp);

        MyVisitor myVisitor = new MyVisitor();
        String result = (String) e.accept(startEndMeasureVisitor);
        assertEquals(result.toString(), "MyResult");
    }
}

And it doesn't work, it sends me the following message :

Property paths must follow a structured type.

So I'm looking for any ideas to make my unit test to work or if you've got working example to share...


Solution

  • Here we go, thanks to tracing function of mockup (very usefull with legacy code), I've got the new version of parseExpression method that answer my question.

    class A implements EdmStructuredType, EdmPrimitiveType {
    
        @Override
        public boolean isCompatible(EdmPrimitiveType edmPrimitiveType) {
            return false;
        }
    
        @Override
        public Class<?> getDefaultType() {
            return null;
        }
    
        @Override
        public boolean validate(String s, Boolean aBoolean, Integer integer, Integer integer1, Integer integer2, Boolean aBoolean1) {
            return false;
        }
    
        @Override
        public <T> T valueOfString(String s, Boolean aBoolean, Integer integer, Integer integer1, Integer integer2, Boolean aBoolean1, Class<T> aClass) throws EdmPrimitiveTypeException {
            return null;
        }
    
        @Override
        public String valueToString(Object o, Boolean aBoolean, Integer integer, Integer integer1, Integer integer2, Boolean aBoolean1) throws EdmPrimitiveTypeException {
            return null;
        }
    
        @Override
        public String toUriLiteral(String s) {
            return null;
        }
    
        @Override
        public String fromUriLiteral(String s) throws EdmPrimitiveTypeException {
            return null;
        }
    
        @Override
        public EdmElement getProperty(String s) {
            return null;
        }
    
        @Override
        public List<String> getPropertyNames() {
            return null;
        }
    
        @Override
        public EdmProperty getStructuralProperty(String s) {
            return null;
        }
    
        @Override
        public EdmNavigationProperty getNavigationProperty(String s) {
            return null;
        }
    
        @Override
        public List<String> getNavigationPropertyNames() {
            return null;
        }
    
        @Override
        public EdmStructuredType getBaseType() {
            return null;
        }
    
        @Override
        public boolean compatibleTo(EdmType edmType) {
            return false;
        }
    
        @Override
        public boolean isOpenType() {
            return false;
        }
    
        @Override
        public boolean isAbstract() {
            return false;
        }
    
        @Override
        public EdmAnnotation getAnnotation(EdmTerm edmTerm, String s) {
            return null;
        }
    
        @Override
        public List<EdmAnnotation> getAnnotations() {
            return null;
        }
    
        @Override
        public FullQualifiedName getFullQualifiedName() {
            return null;
        }
    
        @Override
        public String getNamespace() {
            return null;
        }
    
        @Override
        public EdmTypeKind getKind() {
            return null;
        }
    
        @Override
        public String getName() {
            return null;
        }
    }
    
    
    private Expression parseExpression(final String expressionString)
            throws UriParserException, UriValidationException {
    
        UriTokenizer tokenizer = new UriTokenizer(expressionString);
    
        Edm edm = mock(A.class, withSettings().defaultAnswer(RETURNS_SMART_NULLS));
        EdmProperty employeeIdTypeEdmElement = mock(EdmProperty.class, RETURNS_SMART_NULLS);
    
        when(edmType.getProperty("EmployeeId")).thenReturn(measureTypeEdmElement);
    
        when(edmType.getKind()).thenReturn(EdmTypeKind.PRIMITIVE);
        when(edmType.isCompatible(new EdmDate())).thenReturn(true);
    
        when(employeeIdTypeEdmElement.getName()).thenReturn("EmployeeId");
        when(employeeIdTypeEdmElement.getType()).thenReturn(edmType);
        when(employeeIdTypeEdmElement.isCollection()).thenReturn(false);
    
    
        final Expression expression = new ExpressionParser(edm, odata).parse(tokenizer, edmType, null, null);
        assertNotNull(expression);
        assertTrue(tokenizer.next(UriTokenizer.TokenKind.EOF));
        return expression;
    }
    

    In case it helps someone, maybee it can be optimized, fill free to propose.