我有一个名为A
的课程和方法method1()
:
Class A{
boolean method1(String path){
File procDir = new File(path);
if(!procDir.exists()){
return false`;
}
if(!procDir.canRead()){
return false;
}
}
}
考虑到以上代码,任何人都会建议,方法是使用方法1和内部方法/变量(procDir.canRead()
)。
答案 0 :(得分:2)
第一个答案是:你不能单凭Mockito。
您需要一个能够模拟对new
的调用的模拟框架。如PowerMock(ito)或JMockit。您可以使用PowerMock here找到有关如何执行此操作的文档。从这个意义上讲,从技术上讲,这是一个已解决的问题 - 它只需要一些麻烦就可以使它工作(如果你得到一个pre-reqs错误,它根本就不起作用)。
但除此之外,还有其他答案:您创建了难以测试代码,现在您正在寻找一个创可贴,以解决您的设计不灵活的后果。
因此,不要花费宝贵的时间来处理PowerMock(ito) - 请遵循您已经掌握的建议并修复测试问题的根本原因。例如,通过使用某种依赖注入来为此代码提供File对象(而不是让代码本身调用new
)。
答案 1 :(得分:0)
这是一个设计问题,因为该方法与File
Explicit Dependencies Principle州:
方法和类应明确要求(通常通过方法参数或构造函数参数)所需的任何协作对象才能正常运行。
考虑到这一点,请考虑重构该方法以明确依赖File
boolean method1(File procDir){
if(!procDir.exists()){
return false`;
}
if(!procDir.canRead()){
return false;
}
return true;
}
这也将依赖项的创建反转到类/方法外部的委托。这也让方法明确说明实际需要的内容。
现在该方法已解耦,可以通过传递适当的文件或模拟来测试该方法。
您还可以考虑抽象File
public interface FileInfo {
boolean exists();
boolean canRead()
}
因为类应该依赖于抽象而不是结核。
boolean method1(FileInfo procDir){
if(!procDir.exists()){
return false`;
}
if(!procDir.canRead()){
return false;
}
return true;
}
FileInfo
的实现可以封装实际的File
并公开所需的行为。
对于测试来说,现在应该更容易通过继承或模拟框架直接模拟/存根/伪造抽象。
FileInfo file = mock(FileInfo.class);
when(file.exists()).thenReturn(true);
when(file.exists()).thenReturn(true);
subject.method1(file);
答案 2 :(得分:0)
您可以使用JUnit的TemporaryFolder规则(或者,如果使用JUnit5,它的equivalent extension)来为您的测试创建输入文件。
然后你会......
method1()
- 以测试快乐路径method1()
以测试!procDir.exists()
悲伤路径测试完成后,JUnit将丢弃临时文件夹,从而坚持自我遏制的测试原则。
这种方法允许您在不进行任何模拟的情况下测试代码,同时仍然是一个独立的单元测试。
或者,您可以隐藏界面后面的File procDir = new File(path);
调用:
public interface FileCreator {
File create(String path);
}
通过简单的实施:
public class FileCreatorImpl implements FileCreator {
public File create(String path) {
return new File(path);
}
}
测试时,您可以将Mock(FileCreator.class)
注入包含method1()
的类的实例中,并按如下方式设置对该实例的期望:
String filePath = "...";
File file = Mockito.mock(File.class);
Mockito.when(fileCreator.create(filePath)).thenReturn(file);
// happy path
Mockito.when(file.exists()).thenReturn(true);
Mockito.when(file.canRead()).thenReturn(true);
assertThat(sut.method1(filePath), is(true));
// sad path 1
Mockito.when(file.exists()).thenReturn(false);
assertThat(sut.method1(filePath), is(false));
// sad path 2
Mockito.when(file.exists()).thenReturn(true);
Mockito.when(file.canRead()).thenReturn(false);
assertThat(sut.method1(filePath), is(false));