【问题标题】:Writing Integration Test of ExpressionVisitor with Olingo / ODATA 4使用 Olingo / ODATA 4 编写 ExpressionVisitor 的集成测试
【发布时间】:2019-06-10 09:27:53
【问题描述】:

我正在使用框架 Olingo 以 Java 语言实现符合 OData 标准第 4 版的 Web 服务。我需要自定义$filter 的响应。我已经实现了一个访客as documented in the quick start。我需要实现一个集成测试来尝试不同类型的语法并防止出现回归错误以防将来维护。

对于 V2,我找到了the following tutorial 和以下代码:

@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();
}

很遗憾,UriParser.parseFilter 在 v4.x 中不存在。

我试过这个:

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");
    }
}

它不起作用,它向我发送以下消息:

属性路径必须遵循结构化类型。

所以我正在寻找任何想法让我的单元测试工作,或者如果你有工作示例要分享......

【问题讨论】:

  • 我只有时间讨论这个问题。 org.apache.olingo.client.api.uri.FilterFactory 也许有用?

标签: java odata olingo


【解决方案1】:

我们开始了,多亏了模型的跟踪功能(对遗留代码非常有用),我有了新版本的 parseExpression 方法来回答我的问题。

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;
}

如果它对某人有帮助,也许可以对其进行优化,请随意填写。

【讨论】:

    【解决方案2】:

    谈到单元测试,我会专注于分别测试每个过滤器方法。就像visitBinaryOperator 根据输入返回一个期望值等等。

    我不是命名方面的专家,但我会将您的测试称为集成测试。在这里,我将专注于测试在测试中准备的FilterOption。在您的原始应用程序中,Apache Olingo 将创建此 FilterOption,这部分(应该)在 Olingo 中进行测试。

    当我使用 Apache Olingo 时,我经常提到 its repository,尤其是 server-testserver-tecsvc。验证事物是如何在 Olingo 本身中进行测试的。

    我建议您查看FilterValidator,因为它可能对您的集成测试有用。

    【讨论】:

    • 好的,关于集成测试,我将重命名我的问题。 Olingo 代码源也是我的主要灵感来源。感谢您的建议,与ExpandParserTest 结合使用似乎是解决我的问题的好方法。我会告诉你它是否有效。
    • 这并不容易...... odata-server-test & odata-server-tecsvc 模块不适用于 4.5.0 olingo maven repo。
    • 是的,我只能在 Maven Central 中找到 4.0.0-beta-02-RC01。您可以尝试使用此版本或自行重写所有内容。我没有看到其他选项:/ 好吧,也许是 e2e 测试的一个选项,您可以使用 OData 客户端或普通 HTTP 客户端对准备好的数据库执行 $filter 请求。老实说,我是这样进行测试并进行单元测试的。
    • 感谢您的建议,这是一个好主意,我已经实现了 rest-assured 和 test-jetty-servlet 来运行一些基本的集成测试:)
    猜你喜欢
    • 2018-12-18
    • 2013-11-25
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2015-05-15
    相关资源
    最近更新 更多