我正在尝试使用Mockito编写"另存为"操作的单元测试。该操作的一部分是制作并显示用户可以在其中输入要保存到的文件的文件。选择文件不是我可以自动化的,因此我想模拟FileDialog和模拟mockedFileDialog.getFiles()
以返回我要"保存"的文件。
问题是文件对话框是在我的"保存为"操作的父类中创建的。when(..)
似乎仅在模拟上工作,但是嘲笑我想测试的课程会打败练习的观点。然后,我仅测试是否调用方法,这不是很有用。我只能在测试中运行AbstractSaveAction.saveNet(..)
,但是这样我就不能确定保存操作实际上是在起作用 - 我只是在测试是否有保存某些东西的方法,但是我无法测试是否有一个调用此功能的事件链。
下面的测试将产生:
saveactionTest.java:[60,24] getfiledialog(java.lang.string,java.lang.string)在应用程序中受到了保护。
测试此操作的正确方法是什么?
要测试的代码
public class SaveAsAction extends AbstractSaveAction {
public SaveAsAction(Controller controller, View view) {
super("", "", controller, view);
}
@Override
public void actionPerformed(ActionEvent e) {
saveAsNet();
}
}
public abstract class AbstractSaveAction extends GuiAction {
public AbstractSaveAction(..) {
//...
}
protected final File saveAsFile(FileDialog fileDialog, String extension) {
//...
}
protected final void saveAsNet() {
FileDialog fileDialog = getFileDialog("Save the world", "xml");
File file = saveAsFile(fileDialog, "xml");
saveNet(file);
}
protected final void saveNet(File file) {
try {
controller.saveAsFile(file);
} catch (TicklishPolarBearException e) {
//Panic
}
}
protected final FileDialog getFileDialog(String title, final String extension) {
FileDialog fileDialog = new FileDialog(view, title, FileDialog.SAVE);
fileDialog.setFile("*." + extension);
fileDialog.setFilenameFilter(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith("." + extension);
}
});
return fileDialog;
}
}
test
@Test
public void performsSaveAsWhenNetHasNoFile()
throws AllKindsOfExceptions {
NetName normalName = new NormalNetName("");
when(mockNet.getName()).thenReturn(normalName);
File file = new File("test.xml");
//This will error out
when(saveAction.getFileDialog("Save the world", "xml")).thenReturn(mockFileDialog);
when(mockFileDialog.getFiles()).thenReturn(new File[]{file});
saveAsAction.actionPerformed(null);
verify(mockController).saveAsFile(file);
}
假设您使用相同的软件包,并且(通过注释)可以从方法中删除 final
限定符,我将考虑将一些protected
设置器方法添加到您可以将模拟的方法注入AbstractSaveAction
中。这有些有争议,但会起作用。
我有一个有效的例子,但是要点是生产代码中的以下内容:
public abstract class AbstractSaveAction extends GuiAction {
// ...
// for tests only. Consider naming as 'testFileDialog' if you prefer
private FileDialog fileDialog = null;
// for tests only
protected void setFileDialog(FileDialog fileDialog) {
this.fileDialog = fileDialog;
}
// for tests only
protected void setController(Controller controller) {
this.controller = controller;
}
protected FileDialog buildFileDialog(String title) {
FileDialog result = null;
if (this.fileDialog != null) {
result = this.fileDialog;
} else {
result = new FileDialog(view, title, FileDialog.SAVE);
}
return result;
}
protected FileDialog getFileDialog(String title, final String extension) {
// This is new. Get a FileDialog, and if in test-mode
// so be it... It is a light-touch.
FileDialog fileDialog = buildFileDialog(title);
// ...
}
}
然后测试看起来像:
@Test
public void performsSaveAsWhenNetHasNoFile() {
SaveAsAction saveAsAction = new SaveAsAction(null, null);
FileDialog mockFileDialog = mock(FileDialog.class);
Controller mockController = mock(Controller.class);
Net mockNet = mock(Net.class);
NetName normalName = new NormalNetName("");
when(mockNet.getName()).thenReturn(normalName);
File file = new File("test.xml");
when(mockFileDialog.getFiles()).thenReturn(new File[]{file});
// these steps are crucial
saveAsAction.setFileDialog(mockFileDialog);
saveAsAction.setController(mockController);
// test
saveAsAction.actionPerformed(null);
verify(mockController).saveAsFile(file);
}