当前位置: 首页 > 面试题库 >

是否真的有必要在JUnit拆卸方法中使对象无效?

都沈浪
2023-03-14
问题内容

我的问题是,此代码是否能证明/否定/否定这样的假设,即在拆解方法中使成员变量无效是有用的?我用JUnit4.8.1测试了它。

JUnit为4个测试中的每一个创建测试类的新实例。每个实例都包含一个对象obj。该obj也作为静态WeakHashMap的键插入。如果并且当JUnit释放其对测试实例的引用时,关联的obj值将被弱引用,因此有资格使用gc。该测试尝试强制使用gc。WeakHashMap的大小将告诉我是否对obj进行了gc化。一些测试使obj变量无效,而另一些则没有。

import org . junit . Before ;
import org . junit . After ;
import org . junit . Test ;
import java . util . ArrayList ;
import java . util . WeakHashMap ;
import java . util . concurrent . atomic . AtomicInteger ;
import static org . junit . Assert . * ;

public class Memory
{
    static AtomicInteger idx = new AtomicInteger ( 0 ) ;

    static WeakHashMap < Object , Object > map = new WeakHashMap < Object , Object > ( ) ;

    int id ;

    Object obj ;

    boolean nullify ;

    public Memory ( )
    {
    super ( ) ;
    }

    @ Before
    public void before ( )
    {
    id = idx . getAndIncrement ( ) ;
    obj = new Object ( ) ;
    map . put ( obj , new Object ( ) ) ;
    System . out . println ( "<BEFORE TEST " + id + ">" ) ;
    }

    void test ( boolean n )
    {
    nullify = n ;
    int before = map . size ( ) ;
    gc ( ) ;
    int after = map . size ( ) ;
    System . out . println ( "BEFORE=" + before + "\tAFTER=" + after ) ;
    }

    @ Test
    public void test0 ( )
    {
    test ( true ) ;
    }

    @ Test
    public void test1 ( )
    {
    test ( false ) ;
    }

    @ Test
    public void test2 ( )
    {
    test ( true ) ;
    }

    @ Test
    public void test3 ( )
    {
    test ( false ) ;
    }

    @ After
    public void after ( )
    {
    if ( nullify )
        {
        System . out . println ( "Nullifying obj" ) ;
        obj = null ;
        }
    System . out . println ( "<AFTER TEST " + id + ">" ) ;
    }

    /**
     * Try to force a gc when one is not really needed.
     **/
    void gc ( )
    {
    ArrayList < Object > waste = new ArrayList < Object > ( ) ;
    System . gc ( ) ; // only a suggestion but I'll try to force it
    list :
    while ( true ) // try to force a gc
        {
        try
            {
            waste . add ( new Object ( ) ) ;
            }
        catch ( OutOfMemoryError cause )
            {
            // gc forced? should have been
            waste = null ;
            break list ;
            }
        }
    System . gc ( ) ; // only a suggestion but I tried to force it
    }
}

我使用命令行界面运行了代码(利用-Xmx128k选项来增加垃圾收集),并得到以下结果

.<BEFORE TEST 0>
BEFORE=1    AFTER=1
Nullifying obj
<AFTER TEST 0>
.<BEFORE TEST 1>
BEFORE=2    AFTER=1
<AFTER TEST 1>
.<BEFORE TEST 2>
BEFORE=2    AFTER=1
Nullifying obj
<AFTER TEST 2>
.<BEFORE TEST 3>
BEFORE=2    AFTER=1
<AFTER TEST 3>

Test0 obj被无效,并且在Test1中被gc’ed。但是Test1 obj没有被无效,它在Test2中被gc’ed了。这表明不需要使对象无效。


问题答案:

JUnit 4.x样式测试和测试套件与JUnit 3.x测试套件的处理方式不同。

简而言之,您 应该在JUnit3风格的测试中将字段设置为null,在JUnit4风格的测试中 无需设置

对于JUnit3.x样式测试,TestSuite包含对其他Test对象(可能是TestCase对象或其他TestSuite对象)的引用。如果您创建一个包含许多测试的套件,那么将TestCase在最外层套件的整个运行过程中对所有叶子对象进行硬引用。如果您的某些TestCase对象在setUp()其中分配了占用大量内存的对象,并且对这些对象的引用存储在未设置为nullin的字段中tearDown(),则可能存在内存问题。

换句话说,对于JUnit
3.x样式测试,要运行的测试的规范引用了实际的TestCase对象。TestCase在测试运行期间,对象可访问的所有对象都将保留在内存中。

对于JUnit4.x样式测试,要运行的测试的规范使用Description对象。该Description对象是一个值对象,它指定要运行的内容,而不是指定如何运行它。测试由Runner接受Description测试或套件的对象并确定如何执行测试的对象运行。甚至将测试状态通知给测试侦听器也使用这些Description对象。

对于JUnit4测试用例默认亚军,JUnit4,保持对测试对象的引用只有大约为测试运行的持续时间。如果您使用自定义运行器(通过@RunWith注释),则该运行器可能会或可能不会长时间保留对测试的引用。

也许您想知道如果在JUnit4样式套件中包含JUnit3样式的测试类会发生什么?JUnit4将调用new TestSuite(Class),它将为TestCase每个测试方法创建一个单独的实例。跑步者将TestSuite在整个测试过程中保持对的引用。

简而言之,如果您正在编写JUnit4风格的测试,则不必担心将测试用例的字段设置为可拆卸null(当然,可以释放资源)。如果您正在编写JUnit3样式的测试,setUp()这些测试在中分配大对象并将这些对象存储在的字段中TestCase,请考虑将字段设置为null



 类似资料:
  • 问题内容: 据我所知,使用Java 8流求和的方法是: 在我看来,这似乎有些cru琐-只是应该放弃lambda和数据流的样板“仪式”。 最佳实践告诉我们,实例比数组更可取,但是对于这种求和,数组看起来更干净: 当然,可以做到这一点: 但这比更长。 我知道这与需要围绕Java的非对象原语对流进行改造的方式有关,但是,我在这里还缺少什么吗?有什么方法可以压缩自动装箱以使其更短吗?还是这只是当前的最新状

  • 问题内容: 有必要避免内存泄漏吗? 问题答案: 不,在这种情况下不需要。并且不会被保留,因此没有强大的保留周期的风险。

  • 问题内容: 如果是这样,为什么会发生此错误?该对象不是或如图所示。 我使用调试我的应用,这张照片摄于。 快速配置: 感谢您的意见,现在我发现是,但新的问题是,如何使再次作品?我想返回如下字符串: 如何重新签署适当的方法? 我尝试了undefined ,不好。看到: 问题答案: JS中的每个对象是否都有toString()方法? 否。只有那些继承自(如所有普通对象一样)或自行定义(或从其自定义原型继

  • 本文向大家介绍抽象类必须要有抽象方法吗?相关面试题,主要包含被问及抽象类必须要有抽象方法吗?时的应答技巧和注意事项,需要的朋友参考一下 不需要,抽象类不一定非要有抽象方法;但是包含一个抽象方法的类一定是抽象类。 示例代码: 上面代码,抽象类并没有抽象方法但完全可以正常运行。

  • 问题内容: 通常,在从DOM上卸载组件之前,将清除计时器。但是,如果我们忘记清除计时器,会有什么副作用? 问题答案: 假设您在某个函数中调用,并且当您导航至另一个组件并且当前组件具有时,如果不清除计时器,则函数将继续执行。 因此,在该函数中,您需要清除计时器,该计时器可以通过以下方式返回: 如React DOCS中所述: 在卸载和销毁组件之前立即调用。使用此方法执行任何必要的清除,例如使计时器无效

  • 我目前正在开发一个允许用户订阅推送通知的web应用程序。我们将订阅存储在根据用户ID映射的数据库表中,当需要发送通知时,我们将查找用户的订阅并发送通知。 我一直遵循以下指南:https://developers.google.com/web/fundamentals/codelabs/push-notifications/ 一切都进行得很顺利,但有些事情感觉不“对”。 在每次页面加载时,服务工作者