1
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()")

但这不是很好。有更好的主意吗?

4

3 回答 3

2

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

基本上,是的。很明显 FindBugs 对 JUnit 测试用例及其工作方式没有特别的了解。(我有点惊讶你甚至在你的单元测试中运行 FindBugs ......)

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

将字段显式初始化为 更简单null。这应该会满足 FindBugs 的要求。


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

因为这样的问题!

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

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

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

一种可能是创建一个虚拟Foo实例,并使用它来初始化foo. 但是添加 SuppressWarnings 更直接...


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

于 2012-11-13T15:19:58.673 回答
1

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

于 2012-11-14T05:53:53.717 回答
0

您能否粘贴一个真实的片段,给您相同的警告,而不是您提供的示例?

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

public class FooTest {
  private Foo foo;

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

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

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

于 2012-11-13T14:48:29.757 回答