不正确的findbugs“非空字段未初始化”junit中的错误

时间:2012-11-13 14:31:31

标签: java findbugs

import org.junit.Test;
import edu.umd.cs.findbugs.annotations.DefaultAnnotation;
import edu.umd.cs.findbugs.annotations.NonNull;

@DefaultAnnotation(NonNull.class)
public class FooTest {
    private Foo foo;

    @Before
    public void setUp() throws ParseException {
        foo = ...;
    }

    @Test
    public void testScenario1() {
        foo.getId();
        ...
    }
}

这导致findbugs失败:

NP: Nonnull field foo is not initialized 
by new FooTest( (NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR)

为什么? FindBugs没有看到这是一个junit测试吗? (因此在执行每个测试之前调用setUp())

一种解决方法是添加此类注释:

@SuppressWarnings(
  value="NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", 
  justification="it is initialized in setUp()")

但那不是很好。 还有什么好主意吗?

3 个答案:

答案 0 :(得分:2)

  

为什么? FindBugs没有看到这是一个junit测试吗? (因此在执行每个测试之前调用setUp())

基本上,是的。很明显,FindBugs不具备JUnit测试用例及其工作原理的特殊知识。 (我甚至有点惊讶你甚至在单元测试中运行FindBugs ......)

  

一种解决方法是添加此类注释...更好的主意吗?

将字段显式初始化为null更为简单。这将满足FindBugs。


  

是的,我犹豫是否在测试中添加了NonNull注释;但测试本身可能包含错误,为什么不呢?为什么不在单元测试中运行FindBugs?

因为这样的问题!

单元测试在质量上与普通代码不同。例如,如果foo字段意外遗留null,那么最糟糕的情况是单元测试会崩溃,您将发现错误并修复它。它不会直接破坏生产代码,如果你习惯于忽略失败的单元测试,它将只会产生任何影响。

  

我无法将foo初始化为null,因为它被定义为NonNull(通过DefaultAnnotation)

根据TimK的回答,这意味着foo必须在构造函数执行完后才为非null。鉴于您已为整个代码库(包括测试用例)指定了不变量,您必须坚持使用它,或者添加例外。

一个kludge可能是创建一个虚拟Foo实例,并使用它来初始化foo。但是添加SuppressWarnings更简单明了......


坦率地说,你需要更深入地思考一下你想用FindBugs实现的目标。在单元测试中运行它似乎会产生比它解决的更多问题。

答案 1 :(得分:1)

注释“@DefaultAnnotation(NonNull.class)”表示foo被视为使用@NonNull注释。这意味着foo 在其生命周期内不允许为空。在测试中,在实例化类和调用setUp的时间之间它为null。所以FindBugs正确地报告了这个问题。

答案 2 :(得分:0)

您是否可以粘贴一个真实的片段,为您提供相同的警告而不是您提供的样本?

原因是昨天我遇到了这个确切的蠢货情况,但这是因为一个错字:

public class FooTest {
  private Foo foo;

  @Before
  public void setUp() throws ParseException {
    Foo foo = ...;
  }

你会注意到我有Foo foo。这定义了foo的本地方法实例并初始化它,而不是初始化私有类属性。

我知道你在上面的代码片段中没有这样做,但我想知道你的项目中的真实代码是否犯了这个错误。这是一个简单的错字检查。