如何在每个测试方法中强制运行静态块?

时间:2011-04-25 23:09:11

标签: java unit-testing junit

我发现执行多个JUnit测试时静态块只运行一次。 如何强制它为每个测试方法运行?我正在使用最新的JUnit 4.8.2

另外,根据xUnit设计原则,每种方法都应该完全独立于其他方法。为什么静态块只能执行一次?

@Test TestMethod1 () {
       Accounts ac = new Accounts();
       ac.method1(); //kill the thread inside
}

@Test TestMethod2 () {
       Accounts ac = new Accounts();
       ac.method2(); // the thread is no longer available!!
}

class Accounts {
   static {
       // initalize one thread to monitor something
   }
}

TestMethod1 TestMethod2 位于不同的测试类中时,甚至会发生这种情况。

5 个答案:

答案 0 :(得分:10)

静态块仅在类加载时执行,因为它们就是这样的:类初始化器。要让多次运行静态块,需要卸载该类(这不是一件容易的事情......)。

如果您需要使用静态块,您可以想出测试它们的方法。为什么不将块解包为公共(静态)方法?你在这个世界所要做的就是测试方法:

 static {
      staticInitMethod();
 }

 public static void staticInitMethod(){
      //insert initialization code here
 }

您也可以使用普通的初始化程序

 {//not static
      //insert initialization code here
 }

尽管如此,事实是大多数代码都不需要像这样使用初始化器。

编辑:结果Oracle喜欢静态方法方法http://download.oracle.com/javase/tutorial/java/javaOO/initial.html

答案 1 :(得分:4)

  

为什么静态块只能执行一次?

因为这是静态初始化程序块的重点!

或者换句话说,如果你想要一些初始化代码执行多次,把它放在一个常规的构造函数或方法中,或者(在极少数情况下)一个非静态初始化器块。


在JUnit的上下文中,使用setUp()tearDown()方法实现测试启动和关闭代码的常规方法。


如果您正在尝试在自己的代码中对静态初始化的执行进行单元测试,那么我认为您处于一条艰难的道路上。但是,对具有静态状态(例如单例)的代码进行单元测试总是很困难......而这也是人们认为静态是一个坏主意的原因之一。

  • 考虑使用依赖注入(又名反转控制)框架而不是单例。

  • 或者,考虑修改单例/静态初始化代码以使其更容易测试。例如,添加一个允许测试重新执行初始化的静态方法。 (在你说这打破单身模式之前:是的,我知道。你需要在设计/实施“纯度”和易于测试之间做出选择。)

答案 2 :(得分:0)

正在测试的类的测试的静态代码是什么?

如果代码是静态的,那么测试可以共享,那么您需要将代码移动到自己的类中。然后要么让测试类构造函数实例化一个静态实例,要么创建一个执行相同操作的测试套件。

如果您希望每个测试都独立,那么将您在静态块中执行的操作移动到setup()/ teardown()方法中,这就是它们的用途。

答案 3 :(得分:0)

当第一次将类加载到JVM中时,静态块仅执行一次。 Junit提供@Before批注,该批注基本上用于测试用例的必需初始化。这可以用于执行类的静态块。例如,我有以下课程Car

    public class Car implements Vehicle{

        private String type = "lmv";    
        static {            
            VehicleFactoryWithoutRefl.getInstance().registerVehicle("car", new Car());
        }
        @Override
        public void moveForward() {
        }

        @Override
        public String getType() {
            return type;
        }

        @Override
        public Vehicle createVehicle() {
            return new Car();
        }



    }

,我想在创建汽车实例之前在Junit中执行此类的静态块。我必须使用setUp() Junit代码在class.forName("package.ClassName")中加载此类。

  public class TestFactory {

        @Before
        public void setUp() {
            try {
                Class.forName("com.cg.dp.factory.Car");
            } catch (ClassNotFoundException e) {
                //e.printStackTrace();
            }
        }

        @Test
        //@Ignore
        public void testFactoryInstanceWithoutRefl() {
            Vehicle v1 = VehicleFactoryWithoutRefl.getInstance().newVehicle("car");
            assertTrue(v1 instanceof Car);
        }
    }

答案 4 :(得分:-3)

嗯......让它非静态?您也可以拥有实例初始化程序块(与静态块相同,只是没有static关键字)。但是,测试设置代码实际上应该采用明确的setUp()@Before方法。