如何解决JUnit:使用构造函数代替@Before
| 我正在使用JUnit4。我看不到在构造函数中进行初始化或使用由0注释的专用init函数之间的区别。这是否意味着我不必为此担心? 在任何情况下,@Before
所提供的不仅仅是在构造函数中进行初始化吗?
解决方法
不,在技术上,使用构造函数初始化JUnit测试装置等同于使用
@Before
方法(由于JUnit为每个@Test
创建了一个新的测试类实例)。唯一的(内涵上的)区别是它破坏了@Before
和@After
之间的对称性,这可能会使某些人困惑。恕我直言,最好遵守约定(使用@Before
)。
还要注意,在JUnit 4和注释之前,有专用的setUp()
和tearDown()
方法-@Before
和@After
注释替换了这些方法,但保留了基本逻辑。因此,使用注释也使从JUnit 3或更早版本进行迁移的人员的生活更加轻松。
显着差异
来自评论的更多详细信息:
“ 0”允许覆盖父类行为,构造函数迫使您调用父类构造函数
构造函数在子类构造函数和@Rule
方法之前运行,@Before
在所有这些方法之后运行
@Before
期间的异常导致@After
方法被调用,构造函数中的异常不
,在某些情况下使用@Before更有意义,因为它在类的构造函数AFTER之后被调用。当您使用带有@Mock注释的Mockito之类的模拟框架时,这种区别很重要,因为在初始化模拟之后,将调用@Before方法。然后,您可以使用模拟为被测类提供构造函数参数。
在使用协作bean的单元测试中,我发现这是非常常见的模式。
这是一个(公认的)示例:
@RunWith(MockitoJUnitRunner.class)
public class CalculatorTest {
@Mock Adder adder;
@Mock Subtractor subtractor;
@Mock Divider divider;
@Mock Multiplier multiplier;
Calculator calculator;
@Before
public void setUp() {
calculator = new Calculator(adder,subtractor,divider,multiplier);
}
@Test
public void testAdd() {
BigDecimal value = calculator.add(2,2);
verify(adder).add(eq(2),eq(2));
}
}
,我更喜欢使用构造函数来初始化我的测试对象,因为它使我可以使所有成员成为“ 17”,以便IDE或编译器告诉我何时构造函数忘记初始化成员并阻止其他方法设置它们。
恕我直言,“ 0”违反了最重要的Java约定之一,即依靠构造函数完全初始化对象!
,我更喜欢将我的灯具声明为final,并在内部或在构造函数中对其进行初始化,这样我就不会忘记对其进行初始化!但是,由于以更用户友好的方式处理@Before中引发的异常,因此我通常在@Before中初始化被测试的对象。
,@Before在任何@Test之前被调用,而不是每个Test-Class一次。
这可用于重置/初始化每个特定测试的数据(例如将变量重置为特定值等)。
以同样的方式,@After可以用于在执行@Test方法之后清理代码。
请参阅:http://junit.sourceforge.net/javadoc/org/junit/Before.html
,构造函数可以存档一件事,但@Before不能存档。
当需要初始化父类中定义的字段时,必须使用构造函数。例如:
abstract class AbstractIT {
int fieldAssignedInSubClass;
public AbstractIT(int fieldAssignedInSubClass) {
this.fieldAssignedInSubClass= fieldAssignedInSubClass;
}
@Before
void before() {
// comsume fieldAssignedInSubClass
}
}
public class ChildIT extends AbstractIT{
public ChildIT() {
// assign fieldAssignedInSubClass by constructor
super(5566);
}
@Before
void before() {
// you cannot assign fieldAssignedInSubClass by a @Before method
}
}
,引用http://etutorials.org/Programming/Java+extreme+programming/Chapter+4.+JUnit/4.6+Set+Up+and+Tear+Down/
您可能想知道为什么应该编写setUp()方法而不是
只需在测试用例的构造函数中初始化字段即可。毕竟,
因为为每个测试创建了一个新的测试用例实例
方法中,构造函数总是在setUp()之前调用。在广阔的
在大多数情况下,您可以使用构造函数代替setUp()
没有任何副作用。
如果您的测试用例是更深层次的继承的一部分
层次结构,您可能希望将对象初始化推迟到
派生类的实例已完全构建。这很好
您可能想使用setUp()而不是
初始化的构造函数。使用setUp()和tearDown()也是
很好地用于文档目的,仅因为它可以编写代码
更容易阅读。
,出于多种原因,使用“ 0”确实有意义。它使您的测试代码更具可读性。它与@After
注释匹配,后者负责释放已使用的资源,并且是counterpart22ѭ注释的对应对象。
,除了构造函数是唯一可以在其中初始化@Rule对象的方法外,没有什么区别:
public class TestClass {
@Rule
public SomeRule rule;
public TestClass() {
// code to initialize the rule field
conf = new RuleConf()
rule = new SomeRule(conf)
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。