java 单元:如何使用 jUnit 和 Mockito 编写测试用例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6036650/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unit: How to write test case using jUnit and Mockito
提问by Thang Pham
I am very new to Mockito and jUnit and TDD in general and I try to learn the right way to do TDD. I need couples of example to kick start my brain. SO please help me
总的来说,我对 Mockito、jUnit 和 TDD 非常陌生,我尝试学习正确的方法来进行 TDD。我需要几个例子来启动我的大脑。所以请帮助我
So I have a method getNameInc(String dirPath, String filenName)
. So given a fileName like bankAccount.pdf
, and if in this folder, no file name bankAccount.pdf
, then return bankAccountAA.pdf
. If there is exist one bankAccount.pdf
then return bankAccountBB.pdf
The increment
is AA-ZZ
. When it reach ZZ
then it roll back to AA
. I already implement the logic of this method. How do I unit test this method using Mockiti and jUnit?
所以我有一个方法getNameInc(String dirPath, String filenName)
。所以给定一个bankAccount.pdf
文件名bankAccount.pdf
,如果在这个文件夹中,没有文件名,则返回bankAccountAA.pdf
。如果存在,bankAccount.pdf
则return bankAccountBB.pdf
The increment
is AA-ZZ
。当它到达时,ZZ
它会回滚到AA
。我已经实现了这个方法的逻辑。如何使用 Mockiti 和 jUnit 对该方法进行单元测试?
EDIT
编辑
Here is the class and methods that are involved.
这是所涉及的类和方法。
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()
will be called in the constructor to pre-generate the hash map
generateIncHashMap()
将在构造函数中调用以预先生成哈希映射
回答by Ladlestein
You are trying to test your getNameInc(..) method, I assume. When you call it, it looks for the files in the directory you specify, and based on what it finds, decorates the name you gave it.
我假设您正在尝试测试您的 getNameInc(..) 方法。当您调用它时,它会在您指定的目录中查找文件,并根据找到的内容装饰您给它的名称。
To make the class unit-testable, you should abstract the dependency on the file system, so that in a mock, you can simulate whatever directory contents you want. Your class will accept an instance of this interface as a dependency, and call it to find out what's in the directory. When you use the class in your program for real, you will supply an implementation of this interface that delegates to the JDK filesystem calls. When you unit-test the class, you will supply Mockito mocks of this interface.
为了使类可单元测试,您应该抽象对文件系统的依赖,以便在模拟中,您可以模拟您想要的任何目录内容。您的类将接受此接口的一个实例作为依赖项,并调用它以找出目录中的内容。当您在程序中实际使用该类时,您将提供该接口的一个实现,该实现委托给 JDK 文件系统调用。当您对类进行单元测试时,您将提供此接口的 Mockito 模拟。
Avoid putting too much logic into the FilesystemImpl class, since you can't write a strict unit test for it. Keep it a very simple wrapper around the filesystem, so that all the intelligent stuff is in Yourclass, which you will write plenty of unit tests for.
避免在 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);
}
}
Since there's a lot of duplication between the tests, you'd probably create a setup method and do some of the work there, and create some instance variables for the tests to use:
由于测试之间有很多重复,您可能会创建一个设置方法并在那里做一些工作,并创建一些实例变量供测试使用:
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...
回答by sMoZely
For what you have described there I wouldn't bother with Mockito, there doesn't seem to be anything to mock (because it is easy to manipulate the file system).
对于您在那里描述的内容,我不会打扰 Mockito,似乎没有什么可模拟的(因为它很容易操作文件系统)。
I would test ... - What happens if I call getNameInc and there are no matching files already - What happens if I call getNameInc and there are files AA-YY there already - What happens if I call getNameInc and file ZZ is there already
我会测试...... - 如果我调用 getNameInc 并且已经没有匹配的文件会发生什么 - 如果我调用 getNameInc 并且那里已经有文件 AA-YY 会发生什么 - 如果我调用 getNameInc 并且文件 ZZ 已经存在会发生什么
The point of TDD though is that you should have already written these tests and then implemented your code to make the tests pass. So you won't really be doing TDD since you already have the code.
不过,TDD 的重点是您应该已经编写了这些测试,然后实现了您的代码以使测试通过。所以你不会真的在做 TDD,因为你已经有了代码。