单元:如何使用jUnit和Mockito编写测试用例
我对Mockito,jUnit和TDD一般都很陌生,我尝试学习正确的TDD方法。我需要几个例子来启动我的大脑。所以请帮助我单元:如何使用jUnit和Mockito编写测试用例
所以我有一个方法getNameInc(String dirPath, String filenName)
。因此给定一个文件名如bankAccount.pdf
,并且如果在此文件夹中没有文件名bankAccount.pdf
,则返回bankAccountAA.pdf
。如果存在一个bankAccount.pdf
则return bankAccountBB.pdf
increment
是AA-ZZ
。当它达到ZZ
时,它会回滚到AA
。我已经实现了这个方法的逻辑。如何使用Mockiti和jUnit单元测试此方法?
编辑
这里是类和所涉及的方法。
public class PProcessor{
private final Map<Integer, String> incMap = new HashMap<Integer, String>();
private String getNameInc(String dirPath, String filenName){
String[] nameList = new File(dirPath).list(new FilenameFilter(){
public boolean accept(File file, String name) {
//only load pdf files
return (name.toLowerCase().endsWith(".pdf"));
}
});
//Return the number of occurance that a given file name appear
//inside the output folder.
int freq = 0;
for(int i=0; i<nameList.length; i++){
if(fileName.equals(nameList[i].substring(0, 8))){
freq++;
}
}
return incMap.get(freq);
}
private void generateIncHashMap(){
incMap.put(new Integer(0), "AA");
incMap.put(new Integer(1), "BB");
incMap.put(new Integer(2), "CC");
...
}
}
generateIncHashMap()
将在构造函数中调用预先生成散列图
对于你已经有描述了我不会打扰的Mockito,似乎没有要任何东西嘲笑(因为操纵文件系统很容易)。
我会测试... - 会发生什么事,如果我叫getNameInc并没有匹配的文件已经 - 如果我叫getNameInc并有文件AA-YY已经有发生 什么 - 如果我叫getNameInc会发生什么并且文件ZZ已经存在
TDD的要点在于你应该已经写了这些测试,然后实现了你的代码以使测试通过。所以你不会真的在做TDD,因为你已经有了代码。
是的,我知道在代码之后执行测试并没有多大意义,但是因为这对我来说是新的。我试图得到TDD – 2011-05-17 21:19:31
您正试图测试您的getNameInc(..)方法,我假设。当你调用它的时候,它会查找你指定的目录中的文件,并根据它找到的内容来修饰你给它的名字。
为了让这个类成为单元可测试的,你应该抽象出对文件系统的依赖关系,以便在模拟中你可以模拟任何你想要的目录内容。你的类将接受这个接口的一个实例作为依赖,并且调用它来找出目录中的内容。当你在你的程序中使用真实的类时,你将提供一个实现这个接口的实现,它将委托给JDK文件系统调用。当您对课程进行单元测试时,您将提供此界面的Mockito模拟。
避免将过多的逻辑放入FilesystemImpl类中,因为您无法为其编写严格的单元测试。把它放在文件系统的一个非常简单的包装中,这样所有的智能材料都放在你的类中,你将为它编写大量的单元测试。
public interface Filesystem {
boolean contains(String dirpath, String filename);
}
public class FilesystemImpl {
boolean contains(String dirpath, String filename) {
// Make JDK calls to determine if the specified directory has the file.
return ...
}
}
public class Yourmainclass {
public static void main(String[] args) {
Filesystem f = new FilesystemImpl();
Yourclass worker = new Yourclass(f);
// do something with your worker
// etc...
}
}
public class Yourclass {
private Filesystem filesystem;
public Yourclass(Filesystem filesystem) {
this.filesystem = filesystem;
}
String getNameInc(String dirpath, String filename) {
...
if (filesystem.contains(dirpath, filename) {
...
}
}
}
public class YourclassTest {
@Test
public void testShouldAppendAAWhenFileExists() {
Filesystem filesystem = Mockito.mock(Filesystem.class);
when(filesystem.contains("/some/mock/path", "bankAccount.pdf").thenReturn(true);
Yourclass worker = new Yourclass(filesystem);
String actual = worker.getNameInc("/some/mock/path", "bankAccount.pdf");
assertEquals("bankAccountAA.pdf", actual);
}
@Test
public void testShouldNotAppendWhenFileDoesNotExist {
Filesystem filesystem = Mockito.mock(Filesystem.class);
when(filesystem.contains("/some/mock/path", "bankAccount.pdf").thenReturn(false);
Yourclass worker = new Yourclass(filesystem);
String actual = worker.getNameInc("/some/mock/path", "bankAccount.pdf");
assertequals("bankAccount.pdf", actual);
}
}
因为有很多的测试之间的重复的,你可能会创建一个安装方法,做一些工作在那里,并创建一些实例变量为测试使用方法:
private static final String TEST_PATH = "/some/mock/path";
private static final String TEST_FILENAME = "bankAccount.pdf";
private Filesystem filesystem;
private Yourclass worker;
@Before
public void setUp() {
filesystem = Mockito.mock(Filesystem.class);
worker = new Yourclass(filesystem);
}
@Test
public void testShouldAppendAAWhenFileExists() {
when(filesystem.contains(TEST_PATH, TEST_FILENAME).thenReturn(true);
String actual = worker.getNameInc(TEST_PATH, TEST_FILENAME);
assertEquals("bankAccountAA.pdf", actual);
}
etc...
shouldnt'FilesystemImpl'实现'Filesystem'而不是'interface'的类? – 2011-05-17 21:00:53
你是对的 - 我已经纠正它。 – Ladlestein 2011-05-17 23:14:04
我认为你错过了模拟的一点。模拟不应该实现任何逻辑。通常它只会根据测试用例返回硬编码值。 – 2011-05-17 20:27:45
@Mike:我已经实现了逻辑。 'getNameInc(String dirPath,String fileName)'方法已经由我实现。我只是想知道如何进行单元测试。它可以是mockito或普通的旧jUnit。我试图学习这个想法。 – 2011-05-17 20:31:45
很高兴你想使用TDD!但是,从你最后的评论中听到的声音就像你先写逻辑......这与TDD工作的方式相反。首先编写一个失败的测试,然后用真实的代码传递测试,然后重构该代码,使其更清晰,但除了通过测试之外,没有其他更多的工作。然后写另一个失败的测试。 Mockito在那里帮助你去除你的课程所依赖的复杂服务。你可以用与这个功能协作的类来更新你的问题吗? – alpian 2011-05-17 23:18:07