2010-05-13 40 views
58

是否有任何最佳实践来让Junit在测试文件中执行一次函数,并且它也不应该是静态的。Junit课前(非静态)

like @BeforeClass on non static function?

这里是一个丑陋的解决方案:

@Before void init(){ 
    if (init.get() == false){ 
     init.set(true); 
     // do once block 
    } 
} 

好这是我不想做的,我期待为一体的综合解决方案的JUnit。

+0

出于兴趣你为什么试图做到这一点? – Goibniu 2010-05-13 09:35:46

+0

那么,我有一个相当大的测试文件和基础测试文件的层次结构,我需要在子测试类中覆盖此操作的可能性。 – Roman 2010-05-13 09:39:29

+1

我有同样的问题,其中只有许多参数化测试中的第一个应该执行登录。 – dokaspar 2012-10-05 14:27:57

回答

14

如果你不想设置静态初始化一次性初始化,并不是特别关注使用JUnit,请看看TestNG。 TestNG支持使用各种配置选项进行非静态,一次性初始化,全部使用注释。

TestNG中,这将相当于:

@org.testng.annotations.BeforeClass 
public void setUpOnce() { 
    // One time initialization. 
} 

对于拆机,

@org.testng.annotations.AfterClass 
public void tearDownOnce() { 
    // One time tear down. 
} 

对于TestNG的相当于JUnit 4的@Before@After的,可以分别使用@BeforeMethod@AfterMethod

0

我从来没有尝试过,但也许你可以创建一个无参数构造函数并从那里调用你的函数?

+0

这会奏效,问题是我需要在扩展此基本测试类的类中覆盖此操作的可能性 – Roman 2010-05-13 09:38:20

+0

@Roman:哦,现在我明白了。将此添加到您的帖子中,此评论使事情变得更清晰。 – Roman 2010-05-13 09:57:51

+0

构造函数将被多次调用测试用例。对于每个测试方法,都将创建新的Test类对象。所以,使用构造函数不是这里的解决方案 – manikanta 2011-09-27 18:46:27

31

使用空的构造函数是最简单的解决方案。您仍然可以覆盖扩展类中的构造函数。

但是对于所有的继承来说它并不是最优的。这就是为什么JUnit 4使用注释代替。

另一种选择是在factory/util类中创建一个辅助方法,并让该方法完成工作。

如果您使用的是Spring,则应考虑使用@TestExecutionListeners注释。 事情是这样的测试:

@RunWith(SpringJUnit4ClassRunner.class) 
@TestExecutionListeners({CustomTestExecutionListener.class, 
    DependencyInjectionTestExecutionListener.class}) 
@ContextConfiguration("test-config.xml") 
public class DemoTest { 

Spring的AbstractTestExecutionListener例如包含您可以覆盖这个空方法:

public void beforeTestClass(TestContext testContext) throws Exception { 
    /* no-op */ 
} 
+0

+1这个技巧解决了我想要使用DbUnit时的问题,并且每个类只加载一次数据集 – Brad 2011-11-29 12:16:06

+0

+1对于那些没有被绑定到Spring的古老版本的人来说,这是完美的...。 :( – 2012-03-22 18:28:57

+0

这个'beforeTestClass()'会在上下文初始化之前或之后调用吗? – Dims 2015-10-06 19:21:19

28

一个简单的if语句似乎工作得也很好:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = {"classpath:test-context.xml"}) 
public class myTest { 

    public static boolean dbInit = false; 

    @Autowired 
    DbUtils dbUtils; 

    @Before 
    public void setUp(){ 

     if(!dbInit){ 

      dbUtils.dropTables(); 
      dbUtils.createTables(); 
      dbInit = true; 

     } 
    } 

... 
+1

好而简单!但是看不到一种方法来简单地调整它以创建非静态的'@ AfterClass'等价物,测试已经运行? – 2015-06-27 07:16:38

+0

请参阅[这里](http:// stackoverflow。com/questions/12087959/junit-run-set-up-method-once/31117171#31117171),该方法的更新应该适用于使用继承的测试类。 – 2015-06-30 09:59:03

-1

更新:请看到樱桃为什么下面的建议是有缺陷的评论。(上午离开答案原样,而不是删除/编辑作为注释,可以提供有用的信息给别人,为什么这是行不通的。)


另一个值得考虑的选择,如果使用依赖注入(如Spring)是@PostConstruct。这将保证依赖注入完成后,这将不会是在构造函数的情况:

@PostConstruct 
public void init() { 
    // One-time initialization... 
} 
+6

在Junit测试的情况下,**非常糟**。 Junit每次运行测试方法时创建测试类实例。所以如果在类中有6个测试方法,一个类构造函数'@ Before'和'@ After'方法将被调用6次!所以在这种情况下'@ PostConstruct'的行为就像'@ Before'注释。你可以简单地测试它:只要在测试类中添加2个测试方法,添加'@PostConstruct public void init(){System.out.println(“started”);}'并在日志中查看它打印多少次。 – Cherry 2014-10-01 06:02:56

+0

有关信息,我刚刚遇到[JUnit文档](http://junit.sourceforge.net/javadoc/org/junit/Test.html),它确认了上面有关JUnit为每个“@”创建实例的注释中描述的内容。测试运行:*“为了运行该方法,JUnit首先构造一个新的类实例,然后调用注释的方法。”* – 2017-09-14 15:01:31

0

The article讨论这个问题2个很不错的解决方案:

  1. “干净”的junit用自定义的Runner(使用接口,但你可以用一个自定义注释来扩展它,例如@BeforeInstance)
  2. Espen之前提到的Spring执行侦听器。
-1

只需使用@BeforeClass

@BeforeClass 
public static void init() { 
} 

它没有意义,因为每个测试是在一个单独的实例中运行init是非静态的。运行init的实例 与任何测试的实例都不匹配。

您可能希望它是非静态的唯一原因是在子类中覆盖它,但是您也可以使用静态方法执行此操作 。只需使用相同的名称,并且只会调用子类init方法。

+0

这整个问题是关于以非静态方式执行它的可能性,如果需要你需要一些类的实例变量。 – 2017-02-02 09:11:34

+0

@SimonForsberg是的,我说这个问题是一个XY问题。该操作说,这个问题正在压倒儿童班的行为。如果这个例子需要实例变量,那么我可能会建议其他的东西。 – fgb 2017-02-02 13:48:21

+0

看到这个评论:http://stackoverflow.com/questions/2825615/junit-before-class-non-static/27730780?noredirect=1#comment2866266_2825615 – 2017-02-02 16:45:13

4

很容易使用@BeforeAllMethods/@AfterAllMethods批注在实例上下文(非静态)内运行一个方法,其中所有注入的值都将可用。

有这个特殊的测试库:

https://mvnrepository.com/artifact/org.bitbucket.radistao.test/before-after-spring-test-runner/0.1.0

https://bitbucket.org/radistao/before-after-spring-test-runner/

唯一的限制:只适用测试。

(我是这个测试库的开发者)

+0

请让我知道你是否要使用图书馆 - 我想获得一些用户体验,以了解这个项目是否对社区有意义。谢谢 – radistao 2017-12-21 11:10:15