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() が呼び出されます)

1 つの回避策は、次のクラス アノテーションを追加することです。

@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 を実行していることに少し驚いています...)

1 つの回避策は、このクラス アノテーションを追加することです ... より良いアイデアはありますか?

フィールドを に明示的に初期化する方が簡単nullです。これで FindBugs は満足するはずです。


はい、テストに NonNull アノテーションを追加することを躊躇しました。しかし、テスト自体にバグが含まれている可能性があります。単体テストで FindBugs を実行しないのはなぜですか?

こんなお悩みから!

単体テストは、通常のコードとは質的に異なります。たとえば、fooフィールドが誤って放置された場合、null起こりうる最悪の事態は単体テストがクラッシュすることであり、バグを見つけて修正します。実稼働コードを直接壊すことはなく、失敗した単体テストを無視する習慣がある場合にのみ影響を与えます。

foo は (DefaultAnnotation によって) NonNull として定義されているため、null に初期化できません。

TimK の回答によるとfoo、コンストラクターの実行が終了した後は、null 以外でなければならないことを意味します。コードベース全体 (テストケースを含む) に対してその不変条件を指定した場合、それに固執するか、例外を追加する必要があります。

1 つの手間は、ダミーFooインスタンスを作成し、それを使用して初期化することfooです。ただし、SuppressWarnings を追加する方が簡単です ...


率直に言って、FindBugs で何を達成しようとしているのかについて、もう少し深く考える必要があります。単体テストで実行すると、解決するよりも多くの問題が発生しているようです。

于 2012-11-13T15:19:58.673 に答える
1

注釈「@DefaultAnnotation(NonNull.class)」は、foo が @NonNull で注釈されているかのように扱われることを意味します。つまり、fooはその存続期間中に null になることはできません。テストでは、クラスがインスタンス化されてからsetUpが呼び出されるまでの間はnullです。そのため、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 に答える