2017-03-15 51 views
0

我有以下试验(简化了此问题):从属功能JUnit测试不能共享静态字段

@FixMethodOrder(MethodSorters.JVM) 
public class ArticleTest { 

    private static Article article; 

    @Test 
    public void testCreateArticle() { 
     articleService.create("My article"); 
     article = articleService.findByTitle("My article"); 
     assertNotNull(article); 
    } 

    @Test 
    public void testUpdateArticle() { 
     article.setTitle("New title"); 
     articleService.save(article); 
     assertNull(articleService.findByTitle("My article")); 
     article = articleService.findByTitle("New title"); 
     assertNotNull(article); 
    } 

} 

testCreateArticle成功通过,但在第一行testUpdateArticle失败,因为articlenull,因而抛一个NPE(虽然第一个测试声称article不是null)。

任何人都明白为什么?请注意,我运行测试与Play框架(它喜欢字节码操作),所以这可能有关...

此外,我知道有依赖测试是一种不好的做法,但IRL,这不是单元测试而是一种测试场景的,所以我只是想给相关测试一个尝试自己理解为什么人们不喜欢他们;)

但无论如何,静态字段都应该是测试之间共享, 我错了吗?


更新:我知道我可以在testUpdateArticle()重建的文章,但真正的测试是比较复杂的(也许我没有创造一个MVCE ...)。假设我有第三个测试依赖于第二个测试(取决于第一个测试)等等。第一个测试不需要任何特别的东西,第二个测试需要创建的文章,第三个需要创建和更新的文章等。我想尽量避免每次重做所有数据库操作,通过保持测试之间的状态(使它们依赖于此)。

+0

也许在这种情况下更好的使用TestNG,它支持依赖测试。 – user1516873

回答

1

更好的方法是使用@Before注释在每次测试之前重新创建文章对象。

@Before 
public void setUp() { 
    articleService.create("My article"); 
} 

这样的文章对象不需要是静态的,使测试更容易。

注意:不要忘记清理的文章中@After方法

@After 
public void tearDown() { 
    articleService.delete("My article"); 
} 
+0

你是对的,在这种情况下,这将是正确的做法。虽然真正的测试有点复杂,但更新了我的问题。 – sp00m

1

我不能重现你的行为:

@FixMethodOrder 
public class RemoveMeTest { 
private static String string; 

@Test 
public void testOne() { 
    string = "foo"; 
} 

@Test 
public void testTwo() { 
    System.out.println("in test two: " + string) ; 
} 
} 

和输出确实是“富”。您是否为您的测试用例配备了特殊配置或测试运行器?

而且测试用例应该真的不依赖于其他测试用例。我也想提一提,即使你的情况更复杂,而其他人也已经提到它) 测试A失败,即使它们工作,B和C也会失败。在你的例子中,当你改变字符串“我的文章”时,你改变了测试A,运行,但B和C失败,即使它们工作。如果C失败,则必须先运行A和B,以确认C再次运行。

最糟糕的是imo:它增加了复杂性,这是完全不必要的。正如我的看法:测试代码与生产代码一样有价值,涉及可读性,复杂性,可维护性等。理解10行代码而不是30行代码要容易得多。你可以相信我的经验。我的意思是:我做错了很多......而现在的自己对过去的自我感到非常愤怒:P。有了这个说法:我更喜欢一个容易理解的测试案例,在n-db往返行程中,从长远来看它便宜得多......