想要但不要援引:Mockito PrintWriter

时间:2016-10-21 09:46:54

标签: java mockito junit4 printwriter powermockito

您好我正在开发一个项目并使用number of results: 100 https://newsroom.uber.com/wp-content/uploads/2015/10/HQ_uberkittens_blog_960x540_r1v1.jpg https://pbs.twimg.com/profile_images/562466745340817408/_nIu8KHX.jpeg http://leecamp.net/wp-content/uploads/kitten-3.jpg ... 类来打开和写入文件。但是当我为相同的情况编写测试用例时,它会在第153行给出以下错误

PrintWriter

代码:(使用龙目岛图书馆)

ProcessImageData.java

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

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

我正在为@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()); } } 模拟一个新的运算符,使用bean注入。我在做什么错?很长一段时间我被困在它上面并没有得到错误? 任何帮助表示赞赏。

已更新

我做了下面建议的更改并更新了代码,但现在我收到了错误:

PrintWriter

2 个答案:

答案 0 :(得分:1)

我在测试中看到3个问题:

  1. 您不会尝试模拟正确的构造函数,实际上在方法execute中,您创建的PrintWriter 只有一个参数当您尝试使用2个参数模拟构造函数时类型为File,类型为File,另一个类型为String
  2. 所以代码应该是:

    PowerMockito.whenNew(PrintWriter.class)
        .withArguments(IMAGE_FILE)
        .thenReturn(mockPrintWriter);
    
    1. 为了能够模拟构造函数,您需要准备创建在这种情况下为ProcessImageData的实例的类,因此您需要在注释{{1}中添加ProcessImageData.class }。 (我不确定那里需要@PrepareForTest

    2. 字段ProcessImageDataTest.class应使用lineIterator进行注释。

    3. 您应该直接验证@Mock 而不是新行,而不是使用新行验证print,而不是更容易出错。

      < / LI>

      我简化了你的代码以显示这个想法。

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

      有关详细信息,请参阅How to mock construction of new objects

        

      如何在writer.close?

      的单元测试中添加验证

      一种方法是通过在单元测试中添加下一行来简单地检查@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"); } } 是否被调用一次:

      close()

答案 1 :(得分: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"方法中将execute添加到构造函数调用中。