2011-05-17 138 views
4

我对Mockito,jUnit和TDD一般都很陌生,我尝试学习正确的TDD方法。我需要几个例子来启动我的大脑。所以请帮助我单元:如何使用jUnit和Mockito编写测试用例

所以我有一个方法getNameInc(String dirPath, String filenName)。因此给定一个文件名如bankAccount.pdf,并且如果在此文件夹中没有文件名bankAccount.pdf,则返回bankAccountAA.pdf。如果存在一个bankAccount.pdfreturn bankAccountBB.pdfincrementAA-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()将在构造函数中调用预先生成散列图

+0

我认为你错过了模拟的一点。模拟不应该实现任何逻辑。通常它只会根据测试用例返回硬编码值。 – 2011-05-17 20:27:45

+0

@Mike:我已经实现了逻辑。 'getNameInc(String dirPath,String fileName)'方法已经由我实现。我只是想知道如何进行单元测试。它可以是mockito或普通的旧jUnit。我试图学习这个想法。 – 2011-05-17 20:31:45

+1

很高兴你想使用TDD!但是,从你最后的评论中听到的声音就像你先写逻辑......这与TDD工作的方式相反。首先编写一个失败的测试,然后用真实的代码传递测试,然后重构该代码,使其更清晰,但除了通过测试之外,没有其他更多的工作。然后写另一个失败的测试。 Mockito在那里帮助你去除你的课程所依赖的复杂服务。你可以用与这个功能协作的类来更新你的问题吗? – alpian 2011-05-17 23:18:07

回答

5

对于你已经有描述了我不会打扰的Mockito,似乎没有要任何东西嘲笑(因为操纵文件系统很容易)。

我会测试... - 会发生什么事,如果我叫getNameInc并没有匹配的文件已经 - 如果我叫getNameInc并有文件AA-YY已经有发生 什么 - 如果我叫getNameInc会发生什么并且文件ZZ已经存在

TDD的要点在于你应该已经写了这些测试,然后实现了你的代码以使测试通过。所以你不会真的在做TDD,因为你已经有了代码。

+0

是的,我知道在代码之后执行测试并没有多大意义,但是因为这对我来说是新的。我试图得到TDD – 2011-05-17 21:19:31

7

您正试图测试您的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... 
+0

shouldnt'FilesystemImpl'实现'Filesystem'而不是'interface'的类? – 2011-05-17 21:00:53

+0

你是对的 - 我已经纠正它。 – Ladlestein 2011-05-17 23:14:04

相关问题