层次化的访客模式和状态管理

问题描述 投票:0回答:1

我正试图找到一个好的方法来管理状态与分层访问者模式和ANTLRs自动生成的基础访问者类.虽然下面的例子是我编造的一些愚蠢的东西,但我相信它有助于理解我想解决的概念。

作为一个例子,让我们说我们有一个类。

public class JavaClassVisitor extends JavaBaseVisitor<List<String>> {

    private Map<String, String> dict = new HashMap<>();
    dict.put("public", "I FOUND A PUBLIC SPECIFIER!");
    dict.put("private", "I FOUND A PRIVATE SPECIFIER")

    private List<String> descriptions = new ArrayList<>();

    @Override
    public List<String> visitParseContext(ParseContext ctx){
         visitChildren(ctx);
         return descriptions;
    }

    @Override
    public List<String> visitClassDeclaration(ClassDeclarationContext ctx){
        IdentifierContext idCtx = ctx.Identifier();
        if(idCtx != null){
          String accessSpecifier = idCtx.getText();
          String description = dict.get(accessSpecifier);
          descriptions.add(description);
        } 
        return visitChildren(ctx); 
    }

    @Override
    public List<String> visitMethodDeclaration(MethodDeclarationContext ctx){
        IdentifierContext idCtx = ctx.Identifier();
        if(idCtx != null){
          String accessSpecifier = idCtx.getText();
          String description = dict.get(accessSpecifier);
          descriptions.add(description);
        }
        return visitChildren(ctx);
    }

}

现在请注意,这个类的可测试性不高,管理类顶部的状态也不可取。然而,我很难想出一种方法来测试访问方法.使用JunitMockito,你可以做以下事情。

public class JavaClassVisitorTest(){

  @Mock
  private ClassDeclarationContext classDecCtx;

  @Mock
  private IdentifierContext idCtx;

  @Before
  public void setup(){
     MockitoAnnotations.init(this);
  }    

  @Test
  public void test(){

     doReturn("public")
      .when(idCtx)
      .Identifier();

     doReturn(idCtx)
      .when(classDecCtx)
      .Identifier();

     JavaClassVisitor vstr = new JavaClassVisitor();
     vstr.visitClassDeclaration(classDecCtx);


  }

}

我理想的情况是想检查,例如,如果idCtx存在,则添加了一个描述,但我不能使用这种方法。我是不是对我想实现的目标持有错误的模式?任何关于如何更好地管理状态的见解都是感激的。

java junit state antlr visitor-pattern
1个回答
1
投票

测试,并不是太难。

假设,你想做一些单元测试。那么你就只看方法的实现,其他的都要模拟。比如说 visitClassDeclaration.

public void thatItProperlyCollectsDescriptionsForVisitedClassDeclarations() {
  // Given
  ClassDeclarationContext classDeclMock = mock(ClassDeclarationContext.class);
  JavaClassVisitor victim = spy(new JavaClassVisitor ());

  // When
  victim.visitClassDeclaration(classDeclMock)

  // Then
  assertTrue(victim.getDescriptions().contains(theExpectedString));  // I leave that to you :D
  verify(victim).visitChildren(classDeclMock);  // it calls the visit children method
}

我想你明白了:该方法需要在描述列表中添加一些东西,并调用visitChildren方法。其他的方法也是一样。

对于集成测试,你可以构造一个测试对象,它是一个比较完整的层次结构,包括Parse、Class和Method声明上下文。但我会把主要工作留在单元测试上,也许用一个简单的mock来测试一个快乐的路径,每个层次上都有一个孩子--只是为了确保所有的层次结构层次真的被访问了。

(代码示例应视为伪代码,我没有测试)

© www.soinside.com 2019 - 2024. All rights reserved.