在jUnit中尝试自动重构时,“文件未同步”

时间:2014-11-06 07:56:02

标签: eclipse junit eclipse-plugin eclipse-jdt

我正在编写一个插件,它根据规则重构项目的整个代码库。由于我想自动测试它,我正在用jUnit编写一些测试。

现在,对于每个测试,我需要设置工作区,创建测试项目,添加一些文件,然后对它们应用重构。如果我只有一个测试,这完全正常,但是一旦我编写第二个测试方法,我得到一个Java Model Exception: Core Exception [code 274] The file is not synchronized with the local file system.

我认为问题与仍在内存中的文件有关,但未正确删除。我尝试了各种删除和刷新项目的方法,但它们都没有完美运行(尽管文件系统中的内容被删除)。

有人知道如何解决这个问题吗?

设置-方法:

@Before
public void setup() {

    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); 

    iProject = root.getProject("MyProject");
    try {
        iProject.create(null);
        iProject.open(null);

        IProjectDescription description = iProject.getDescription();
        description.setNatureIds(new String[] { JavaCore.NATURE_ID });
        iProject.setDescription(description, null);

        iJavaProject = JavaCore.create(iProject);

        IFolder binFolder = iProject.getFolder("bin");
        binFolder.create(true, true, null);
        iJavaProject.setOutputLocation(binFolder.getFullPath(), null);

        sourceFolder = iProject.getFolder("src");
        sourceFolder.create(true, true, null);

        IClasspathEntry[] buildPath = {
                JavaCore.newSourceEntry(iProject.getFullPath()
                        .append("src")),
                JavaRuntime.getDefaultJREContainerEntry() };

        iJavaProject.setRawClasspath(buildPath, iProject.getFullPath()
                .append("bin"), null);
        // create package
        iPackage = iJavaProject.getPackageFragmentRoot(sourceFolder)
                .createPackageFragment(PACKAGE_NAME, false, null);

        //create the java class
       ICompilationUnit iUnitUtilityClass = iPackage.createCompilationUnit("Bars.java", existingUtilityClass, false, null);
        ....
        //more files

清理方法:

@After
public void cleanup() throws CoreException, InterruptedException {
    //various ways of deleting the project          
    iProject.delete(true, true, null);

    iProject.delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT | IResource.DEPTH_INFINITE, new NullProgressMonitor());

    ResourcesPlugin.getWorkspace().delete(new IResource[] {iProject.getProject()}, true, null);
    iProject = null;

    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
            root.delete(true, true, null);      
}

试验方法:         ....

    ICompilationUnit iUnit = iPackage.createCompilationUnit("Bar.java",
            fileName, false, null);


    MoveUtilityMethodsToUtilityClassHandler handler= new  MoveUtilityMethodsToUtilityClassHandler();
    iUnit.save(null, true);
    Result result = handler.handle(iUnit); //<--- here, the exception is thrown
    ....

例外:

Java Model Exception: Core Exception [code 274] The file is not synchronized with the local file system.
at org.eclipse.jdt.internal.core.BatchOperation.executeOperation(BatchOperation.java:50)
at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:728)
at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2345)
at org.eclipse.jdt.core.JavaCore.run(JavaCore.java:5332)
at org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationStateChange.perform(DynamicValidationStateChange.java:116)
at org.eclipse.ltk.core.refactoring.CompositeChange.perform(CompositeChange.java:278)
at ch.ergon.advancedrefactoring.handlers.MoveUtilityMethodsToUtilityClassVisitor.moveTo(MoveUtilityMethodsToUtilityClassVisitor.java:293)
at ch.ergon.advancedrefactoring.handlers.MoveUtilityMethodsToUtilityClassVisitor.visit(MoveUtilityMethodsToUtilityClassVisitor.java:121)
at org.eclipse.jdt.core.dom.MethodDeclaration.accept0(MethodDeclaration.java:489)
at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2514)
at org.eclipse.jdt.core.dom.ASTNode.acceptChildren(ASTNode.java:2585)
at org.eclipse.jdt.core.dom.TypeDeclaration.accept0(TypeDeclaration.java:484)
at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2514)
at org.eclipse.jdt.core.dom.ASTNode.acceptChildren(ASTNode.java:2585)
at org.eclipse.jdt.core.dom.CompilationUnit.accept0(CompilationUnit.java:220)
at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2514)
at ch.ergon.advancedrefactoring.handlers.MoveUtilityMethodsToUtilityClassHandler.handle(MoveUtilityMethodsToUtilityClassHandler.java:45)
at ch.ergon.advancedrefactoring.UtilityRefactorTest.testMoveToExistingUtiliyClass(UtilityRefactorTest.java:197)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

2 个答案:

答案 0 :(得分:0)

错误消息显示有人在未告知Eclipse的情况下更改了文件。因此,您需要查找使用普通Java API修改文件的代码或在测试或Eclipse之外运行的代码以及更改文件的代码(如Windows上的文件索引器)。

您还可以尝试使用IResourcerefreshLocal()强制刷新。

答案 1 :(得分:0)

我用一个肮脏的解决方法解决了问题(好吧,不是真的)。​​

由于项目没有被彻底删除,我只为我创建的每个项目使用不同的名称。

因此,在第一次测试中,项目在第二次测试&#34; Project1&#34;中命名为&#34; Project0&#34;,依此类推。这很有效。

@Before
public void setup() {
    projectName = "Project" + projectCount++;
    System.out.println("Create Project " + projectName);
    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); 

    iProject = root.getProject(projectName);
    try {
        iProject.create(null);
    .....

不是我最喜欢的解决方案,但它确实有效......而且Eclipse无论如何都会在测试后清理工作区。