Java Junit读取并处理文件的应用程序

Java Junit读取并处理文件的应用程序,java,junit,Java,Junit,我正在开发一个Java应用程序,它将读取一个文件,然后在将其读入内存后将进行进一步的处理 文件读取的要求是代码应该从“当前工作目录””中读取。 我写了一个方法如下: public List<String> processFile(String fileName){ String localPath = FileSystems.getDefault().getPath(".").toAbsolutePath() + fileName; } 公共列表进程文件(字符串文件名){

我正在开发一个Java应用程序,它将读取一个文件,然后在将其读入内存后将进行进一步的处理

文件读取的要求是代码应该从“当前工作目录””中读取。 我写了一个方法如下:

public List<String> processFile(String fileName){
    String localPath = FileSystems.getDefault().getPath(".").toAbsolutePath() + fileName;
}
公共列表进程文件(字符串文件名){
字符串localPath=FileSystems.getDefault().getPath(“.”)。toAbsolutionPath()+文件名;
}
此方法将文件转换为它返回的ArrayList。 然后需要使用此arraylist进行进一步处理

public boolean workOnFile(){
   List<String> records = processFile("abc.txt");
   // additional logic
}
public boolean worknfile(){
列表记录=进程文件(“abc.txt”);
//附加逻辑
}
我对如何Junit文件读取部分感到困惑,因为需要从“工作目录”读取文件,所以无论用户在哪里运行程序,都会从工作目录读取输入文件

但是,对于Junit,我的测试文件将位于“\src\main\resources”中 因此,“processFile”方法不会读取测试文件,因为它在“当前工作目录”中查找文件

一种想法是,我不需要Junit来读取文件,但整个应用程序在读取文件后会做一些事情——因此,我是否有一些“测试”规定,在执行Junit时,我在Junit中读取文件,然后在测试中的类中有规定来注入testArrayList

@Test
public void doSomeValidation() {
    String testFile = "XYZ.txt";
    ClassUnderTest fixture = new ClassUnderTest();
    List<String> testList = /** read file in Junit from /src/main/resources/ **/
    /** inject this testList into ClassUnderTest **/
    fixture.setFileContent(testList );

    /** then continue testing the actual method that needs to be tested **/
    assertNotFalse(fixture.workOnFile());
}
@测试
公共无效doSomeValidation(){
字符串testFile=“XYZ.txt”;
ClassUnderTest夹具=新ClassUnderTest();
List testList=/**从/src/main/resources/读取Junit中的文件**/
/**将此测试列表注入ClassUnderTest**/
fixture.setFileContent(testList);
/**然后继续测试需要测试的实际方法**/
assertNotFalse(fixture.worknfile());
}
为了实现这一点,我必须更改需要测试的实际类,以便能够注入读取的测试文件。大致如下:

public class ClassUnderTest(){
   public List<String> processFile(String fileName){
    String localPath = FileSystems.getDefault().getPath(".").toAbsolutePath() + fileName;
   }
    /** new method used in junit to inject to **/
    public void setFileContent(List<String> input){
        this.input = input;
    }
   /** modify this method first check if injected arraylist not null **/
   public boolean workOnFile(){
      List<String> records;
      if(this.input == null){
         /** in actual runs this block will execute **/
         this.input = processFile("abc.txt");
      }
      // additional logic
   }

}
public类ClassUnderTest(){
公共列表进程文件(字符串文件名){
字符串localPath=FileSystems.getDefault().getPath(“.”)。toAbsolutionPath()+文件名;
}
/**junit中用于注入的新方法**/
public void setFileContent(列表输入){
这个输入=输入;
}
/**修改此方法首先检查注入的arraylist是否不为null**/
公共布尔工作文件(){
列出记录;
if(this.input==null){
/**在实际运行中,将执行此块**/
this.input=processFile(“abc.txt”);
}
//附加逻辑
}
}
这条路对吗? 不知怎么的,我觉得我在乱搞代码,只是为了让它更易于测试?
这是正确的方法吗?

一个简单的解决方案:更改接口以便于测试

意思是:

  • 有一个方法将文件名“放在本地路径中”(与
    processFile()方法构建该文件名的方式相同)
  • 然后将该操作的结果传递给
    processFile()
    方法
换句话说:您的代码限制了该方法始终计算完整路径本身。这使得很难控制,也很难测试

因此:将你的问题分解成可能的最小部分

那么您只需要测试:

  • 您的新方法
    Path getLocalPathFor(stringfilename)
    执行它应该执行的操作
  • 然后,您的方法
    processFile(Path absFilePath)
    执行它需要执行的操作(现在,您可以使用位于任何位置的路径来测试该方法,而不仅仅是在本地目录中)

为什么要这样做?请改用硬编码列表,这样您就知道永远不会有FileNotFound异常,或者有人意外更改文件内容,使您的测试崩溃,…因此新方法路径getLocalPathFor(String fileName)什么时候调用此函数-仅在单元测试时或在实际运行时调用。我仍然不知道这有什么帮助,因为在单元测试时,我希望从/src/main/resources/读取文件,而在实际执行时,该文件应该从当前工作目录读取。很抱歉,我没有理解您的错误answer@akila关键是:当你分开的时候将功能集成到不同的方法中,然后测试变得更容易。您仍然可以决定使用一个同时调用这两种方法的方法。但主要工作是测试“查找本地路径”和“读取并处理某些文件”可以和应该分开。这样,当您还编写调用其他两个方法的最终方法时,您只需要一个小的集成测试。