想要但不要援引:Mockito PrintWriter
嗨,我正在研究一个项目,并使用PrintWriter
类在文件中打开和写入。 但是当我为相同的情况编写测试用例时,它会在第153行给出以下错误
Wanted but not invoked: mockPrintWriter.println("ID url1 "); -> at xyzverify(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 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 exepctedFileContentOutput = Arrays.asList(ID3 + SPACE + URL2 + NEWLINE); verify(exepctedFileContentOutput, 1, 1); } private void verify(List 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
的新操作符,使用bean注入。 我在做什么错? 很长一段时间我被困在它上面并没有得到错误? 任何帮助表示赞赏。
更新 :
我做了下面建议的更改并更新了代码,但现在我收到错误:
Wanted but not invoked: mockPrintWriter.print("ASIN2 url1 "); -> at softlines.ctl.ruleExecutor.tasks.ProcessImageDataTest.verify(ProcessImageDataTest.java:153) However, there were other interactions with this mock: -> at 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) –
我在你的测试中看到3个问题:
- 你不试图模拟正确的构造函数 ,实际上在方法
execute
,你创建的PrintWriter
只有一个File
类型的参数 ,而你试图用2个参数模拟构造函数 ,类型为File
,另一个类型为String
。
所以代码应该是:
PowerMockito.whenNew(PrintWriter.class) .withArguments(IMAGE_FILE) .thenReturn(mockPrintWriter);
-
为了能够模拟构造函数,您需要准备创建实例的类,在这种情况下是
ProcessImageData
,因此您需要在注释@PrepareForTest
添加ProcessImageData.class
。 (我不确定那里是否需要ProcessImageDataTest.class
) -
字段
lineIterator
应使用@Mock
注释。 -
您应该在没有新行的情况下直接validation
println
,而不是使用新行validationprint
,而不是更容易出错。
我简化了你的代码来展示这个想法。
假设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()); } } } }
我的unit testing将是:
@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"); } }
有关更多详细信息,请参阅如何模拟新对象的构造 。
如何在writer.close的unit testing中添加validation?
一种方法是通过在unit testing中添加下一行来简单地检查close()
被调用一次:
Mockito.verify(mockPrintWriter, Mockito.times(1)).close();
您的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
子句,或者需要在execute
方法中向构造函数调用添加"UTF-8"
。