`

JUnit 单元测试

    博客分类:
  • J2EE
阅读更多
 
测试的分类:
http://stackoverflow.com/questions/520064/what-is-unit-test-integration-test-smoke-test-regression-test
http://stackoverflow.com/questions/4904096/whats-the-difference-between-unit-functional-acceptance-and-integration-test
http://stackoverflow.com/questions/3370334/difference-between-acceptance-test-and-functional-test
引用
Unit test
Integration test
Functional & Acceptance test
Regression test
and so on
Unit test  and Integration test 的详细对比:
http://zeroturnaround.com/rebellabs/the-correct-way-to-use-integration-tests-in-your-build-process/


Martin Fowle - Mocks Aren't Stubs:
http://martinfowler.com/articles/mocksArentStubs.html



Mock frameworks of Unit Test: Mockito JMockit EasyMock Jmock and so on.


junit3及之前,遵从“约定优于配置”的原则,单元测试类一般遵从以下原则:
引用
1 单元测试类继承  junit.framework.TestCase
2 单元测试类命名为 [被测试的类的类名]Test
3 测试方法(必须)命名为 test[业务逻辑模块],并且为 public void 的
4 failing开头的测试方法会被skipped/ignored


junit4之后,引入的注解的方式。如果你使用的是4+的junit,请优先选择注解的方式,原因见:
http://stackoverflow.com/questions/2635839/junit-confusion-use-extend-testcase-or-test
引用
The @Test annotaton is more explicit and is easier to support in tools (for example it's easy to search for all tests this way)
Multiple methods can be annotated with @Before/@BeforeClass and @After/@AfterClass providing more flexibility
Integrated support for testing for expected exceptions using expected=
Support for the @Ignored annotation
比如,如果使用的是3的格式,则若单元测试类中没有任何test开头的测试方法的话,直接在单元测试类上run as - junit test 是会报下面错误的:
junit.framework.AssertionFailedError: No tests found in com.xxx.MailComposeTest
如果项目是基于maven的,这点尤其烦人,因为会发生 mvn test 失败的事情。如果是用 4 的话,在单元测试类上加一个 @Ignored ,就可以轻松的忽略掉该单元测试类,使之不会被mvn test所测试。
附:
How to skip a test case in Junit
http://junit.org/node/291
4的方式,单元测试类是不需要继承TestCase的,可以是普通的java类;加在测试方法上的@Test即是单元测试的入口;测试类上可以通过加@RunWith(如@RunWith(value=SpringJUnit4ClassRunner.class))来指定junit内置runner之外的其他runner。另外切记:请不要混合使用3的 extends TestCase 和4的 @Test,即不要这样做:测试类继承了TestCase,而其中的测试方法又添加了@Test注解。因为如果你这样做了的话,你会发现那些未遵循3的测试方法命名规范(形如testXxx)的方法,是无法被执行单元测试的,尽管它已经被添加了@Test注解!(遵循了3的测试方法命名规范的方法可以被执行单元测试,这说明,混合使用3的 extends TestCase 和4的 @Test最终用的是3的方式,4的方式变得不再起作用)。
另小注:4注解的@Ignore不存在与3的配置的冲突。



测试结果为Failures和Errors的单元测试都被认为是失败的单元测试,都是会造成maven项目build失败的。
测试方法中如果捕获到了Exception(并且未catch),则测试结果为Errors;有时你可能不希望某类异常造成Junit测试的失败,比如自定义的(继承了runtimeexception的)unchecked exception,则使用4的注解的方式,就可以轻松的将某类异常忽略掉,使其不至于导致单元测试的失败。具体有两种配置方式可供选择:
http://stackoverflow.com/questions/11426042/good-practice-for-testing-exceptions-in-junit
引用
@Rule
public ExpectedException exception = ExpectedException.none();

@Test
public void checkNullObject() throws CustomException {
    exception.expect(CustomException .class);
    MyClass myClass= null;
    MyCustomClass.get(null);
}
@Test(expected=CustomException.class)
public void checkNullObject() throws CustomException {
    MyClass myClass= null;
    MyCustomClass.get(null);    
}
两种方式孰优孰劣参见链接出处




当Junit遇到System.exit():
单元测试的时候经常会碰到某个方法在某些分支会调用System.exit(exitcode)方法,而一旦程序运行到System.exit()方法,整个JVM就退出了,而junit也是运行于此JVM之上,即整个测试就(无任何返回结果地)终止了。
Junit+System.exit()会jvm退出、测试终止,但在eclipse(3.7 indigo)下,有个很奇怪的现象:"Stop Junit Test Run"按钮会一直保持在可点击状态,给人一种“单元测试并未终止只是被挂起无法继续执行下去”的错觉:

这应该是eclipse的bug:jvm退出,单元测试被强制终止,没有任何的单元测试结果被返回(success、errors、failures,etc),而"Stop Junit Test Run"按钮的状态是基于单元测试的返回结果的,无结果返回,无按钮状态变化。
解决办法:
http://stackoverflow.com/questions/309396/java-how-to-test-methods-that-call-system-exit
引用
其中的最佳答案给出的两个解决思路不错:
1 程序中不要使用System.exit(),而改为抛出一个unchecked exception,如抛出本博文上面部分说的一个自己定义的runtimeexception的子类:SomeAppException,并将测试方法声明为对SomeAppException是expected的。
2 在单元测试类中使用SecurityManager,来让单元测试方法可以检测到System.exit()调用,在jvm因其退出前可以做些额外的处理工作






Junit与多线程:
Junit的测试主线程,在最后是通过执行System.exit(0)来退出的。System.exit是直接退出jvm,所以,如果测试运行期间你启动了其他线程(且未join入测试主线程),则这些线程就都因为jvm的退出而无法再执行下去。参考资料:
http://www.iteye.com/topic/154410
另外,junit测试主线程之外的其他线程抛出的Unckecked Exceptions,junit是捕获不到的。这里有个很经典的例子:
http://stackoverflow.com/questions/4039873/weird-problem-using-junit-in-multi-thread-environment
  • 大小: 5.6 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics