2016-10-21 68 views
1

嗨我正在一個項目和使用PrintWriter類打開和寫入文件。但是,當我在爲同一寫測試用例它給了以下錯誤在線路153想要但不是援引:Mockito PrintWriter

Wanted but not invoked: 
    mockPrintWriter.println("ID url1 
    "); 
-> at x.y.z.verify(ProcessImageDataTest.java:153) 
Actually, there were zero interactions with this mock. 

代碼:(使用龍目島庫)

ProcessImageData.java

@Setter 
@RequiredArgsConstructor 
public class ProcessImageData implements T { 
    private final File newImageDataTextFile; 

    @Override 
    public void execute() { 
     LineIterator inputFileIterator = null; 
     try { 
     File filteredImageDataTextFile = new File(filteredImageDataTextFilepath); 

      PrintWriter writer = new PrintWriter(newImageDataTextFile); 
      inputFileIterator = FileUtils.lineIterator(filteredImageDataTextFile, StandardCharsets.UTF_8.displayName()); 
      while (inputFileIterator.hasNext()) { 
        if(someCondition) 
      **Line51**   writer.println(imageDataFileLine); 
        //FileUtils.writeStringToFile(newImageDataTextFile, imageDataFileLine + NEWLINE, true); 
       } 
      }   

     } catch (Exception e) { 

     } finally { 
      LineIterator.closeQuietly(inputFileIterator); 
**LINE63**   writer.close(); 
     } 
    } 

ProcessImageDataTest.java

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ ProcessImageData.class, FileUtils.class, Printwriter.class }) 
public class ProcessImageDataTest { 

private ProcessImageData processImageData; 

private static final String FILTERED_IMAGE_DATA_TEXT_FILE_PATH = "filteredFilepath"; 
private File FILTEREDFILE = new File(FILTERED_PATH); 
private static final File IMAGE__FILE = new File("imageFilePath"); 

private LineIterator lineIterator; 
@Mock 
private PrintWriter mockPrintWriter; 

@Before 
public void init() throws Exception { 
    MockitoAnnotations.initMocks(this); 

    processImageData = new ProcessImageData(Palettes_file, FILTERED_PATH, IMAGE_FILE); 

    PowerMockito.mockStatic(FileUtils.class); 
    PowerMockito.whenNew(PrintWriter.class).withArguments(IMAGE_FILE).thenReturn(mockPrintWriter); 

    PowerMockito.when(FileUtils.lineIterator(FILTERED_FILE, StandardCharsets.UTF_8.displayName())).thenReturn(lineIterator); 
    PowerMockito.when(lineIterator.hasNext()).thenReturn(true, true, false); 

} 

@Test 
public void testTaskWhenIDInDBAndStale() throws IOException { 
    PowerMockito.when(lineIterator.nextLine()).thenReturn(ID2 + SPACE + URL1, ID1 + SPACE + URL2); 

    processImageData.execute(); 

    List<String> exepctedFileContentOutput = Arrays.asList(ID2 + SPACE + URL1 + NEWLINE); 
    verify(exepctedFileContentOutput, 1, 1); 
} 


@Test 
public void testTaskWhenIDNotInDB() throws IOException { 
    PowerMockito.when(lineIterator.nextLine()).thenReturn(ID2 + SPACE + URL1, ID3 + SPACE + URL2); 

    processImageData.execute(); 

    List<String> exepctedFileContentOutput = Arrays.asList(ID3 + SPACE + URL2 + NEWLINE); 
    verify(exepctedFileContentOutput, 1, 1); 
} 

private void verify(List<String> exepctedFileContentOutput, int fileWriteTimes, int fileReadTimes) throws IOException { 
    for (String line : exepctedFileContentOutput){ 
**Line153**      Mockito.verify(mockPrintWriter, Mockito.times(fileWriteTimes)).print(line); 
    } 

    PowerMockito.verifyStatic(Mockito.times(fileReadTimes)); 
    FileUtils.lineIterator(FILTERED_IMAGE_DATA_TEXT_FILE, StandardCharsets.UTF_8.displayName()); 
} 

} 

我在嘲笑一個新的PrintWriter的運算符也是使用beans注入的。我在做什麼錯誤?我很久沒有接受這個錯誤了嗎? 任何幫助表示讚賞。

更新

我建議以下變化和更新的代碼,但現在我得到的錯誤:

Wanted but not invoked: mockPrintWriter.print("ASIN2 url1 "); -> 
at softlines.ctl.ruleExecutor.tasks.ProcessImageDataTest.verify‌​(ProcessImageDataTes‌​t.java:153) 
However, there were other interactions with this mock: -> at softlines.ctl.ruleExecutor.tasks.ProcessImageData.execute(Pr‌​ocessImageData.java:‌​51) -> 
at softlines.ctl.ruleExecutor.tasks.ProcessImageData.execute(Pr‌​ocessImageData.java:‌​51) -> 
at softlines.ctl.ruleExecutor.tasks.ProcessImageData.execute(Pr‌​ocessImageData.java:‌​58) – 
+1

儘量不要隱瞞留下了'捕獲任何異常'子句爲空。你能包括一張印刷品或其中的東西嗎? – SomeJavaGuy

+0

請注意'lineIterator'上缺少'@ Mock'。相反,要用新行驗證'print',嘗試驗證'println'沒有新行,它不太容易出錯,並告訴我它是否有幫助 –

回答

1

我看到在您的測試3個問題:

  1. 你不要試圖嘲笑正確的構造,確實是在方法execute,創建您PrintWriter只有一個File類型的參數而您嘗試模擬構造函數與2個參數類型FileString類型中的另一個。

因此,代碼而應是:

PowerMockito.whenNew(PrintWriter.class) 
    .withArguments(IMAGE_FILE) 
    .thenReturn(mockPrintWriter); 
  • 爲了能夠嘲笑你需要準備的類創建它是實例的構造在這種情況下爲ProcessImageData,所以您需要在註釋@PrepareForTest中添加ProcessImageData.class。(我不確定那裏需要ProcessImageDataTest.class

  • 該字段lineIterator應註明@Mock

  • 而是用一個新行驗證print的,應當驗證直接println沒有新線它是非常不容易出錯。


  • 我簡化你的代碼顯示的想法。

    假設ProcessImageData是:然後

    public class ProcessImageData { 
    
        private final File newImageDataTextFile; 
    
        public ProcessImageData(final File newImageDataTextFile) { 
         this.newImageDataTextFile = newImageDataTextFile; 
        } 
    
        public void execute() throws Exception{ 
         try (PrintWriter writer = new PrintWriter(newImageDataTextFile)) { 
          LineIterator inputFileIterator = FileUtils.lineIterator(
           newImageDataTextFile, StandardCharsets.UTF_8.displayName() 
          ); 
          while (inputFileIterator.hasNext()) { 
           writer.println(inputFileIterator.nextLine()); 
          } 
         } 
        } 
    } 
    

    我的單元測試是:

    @RunWith(PowerMockRunner.class) 
    @PrepareForTest({ProcessImageData.class, FileUtils.class}) 
    public class ProcessImageDataTest { 
    
        private File file = new File("imageFilePath"); 
    
        private ProcessImageData processImageData; 
        @Mock 
        private PrintWriter mockPrintWriter; 
        @Mock 
        private LineIterator lineIterator; 
    
        @Before 
        public void init() throws Exception { 
         MockitoAnnotations.initMocks(this); 
    
         processImageData = new ProcessImageData(file); 
         PowerMockito.whenNew(PrintWriter.class) 
          .withArguments(file) 
          .thenReturn(mockPrintWriter); 
         PowerMockito.mockStatic(FileUtils.class); 
         PowerMockito.when(
          FileUtils.lineIterator(file, StandardCharsets.UTF_8.displayName()) 
         ).thenReturn(lineIterator); 
         PowerMockito.when(lineIterator.hasNext()).thenReturn(true, true, false); 
        } 
    
        @Test 
        public void testExecute() throws Exception { 
         PowerMockito.when(lineIterator.nextLine()).thenReturn("Foo", "Bar"); 
         processImageData.execute(); 
         Mockito.verify(mockPrintWriter, Mockito.times(1)).println("Foo"); 
         Mockito.verify(mockPrintWriter, Mockito.times(1)).println("Bar"); 
        } 
    } 
    

    欲瞭解更多詳情,請參閱How to mock construction of new objects


    how can I add verification in unit test for writer.close?

    的一種方法是簡單地檢查close()在被調用一次加入下一行到你的單元測試:

    Mockito.verify(mockPrintWriter, Mockito.times(1)).close(); 
    
    +0

    嘿謝謝。這工作。但它顯示另一個錯誤: 通緝但未調用: mockPrintWriter.print(「ASIN2 url1 」); - >在softlines.ctl.ruleExecutor.tasks.ProcessImageDataTest.verify(ProcessImageDataTest.java:153) 然而,有與該模擬的其它交互: - 在softlines.ctl.ruleExecutor.tasks.ProcessImageData.execute>( ProcessImageData.java:51) - > at softlines.ctl.ruleExecutor.tasks.ProcessImageData.execute(ProcessImageData.java:51) - > at softlines.ctl.ruleExecutor.tasks.ProcessImageData.execute(ProcessImageData.java:58) – user2696258

    +0

    我已經更新了這個問題。你能否說出爲什麼特定的模擬交互沒有被調用。 – user2696258

    +1

    是的,謝謝它的工作。刪除換行工作! – user2696258

    0

    你的PrintWriter的施工模擬不匹配。你告訴PowerMockito來回報您的模擬像這樣:

    PowerMockito.whenNew(PrintWriter.class).withArguments(IMAGE_FILE , StandardCharsets.UTF_8.name()).thenReturn(mockPrintWriter); 
    

    所以,你不得不說:

    new PrintWriter(IMAGE_FILE, "UTF-8"); // 2 arguments 
    

    但不是在被測試的代碼你execute方法,你這樣做:

    PrintWriter writer = new PrintWriter(newImageDataTextFile); // only 1 argument 
    

    因此,您需要更改PowerMockito withArguments子句,或者您需要將"UTF-8"添加到中的構造函數調用中方法。