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()")
但那不是很好。 还有什么好主意吗?
答案 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的本地方法实例并初始化它,而不是初始化私有类属性。
我知道你在上面的代码片段中没有这样做,但我想知道你的项目中的真实代码是否犯了这个错误。这是一个简单的错字检查。