@Before
符号,因为多个测试需要在运行之前创建类似的对象。
但是,在测试用例函数作为全局对象之前实例化对象和放入@Before
内部之间我没有区别。
例如,我正在测试我的国际象棋程序,我正在测试我的Piece对象是否移动到正确的位置:
public class PawnTest { //The Test Class itself
Board board = new Board();
@Test
/**
* Testing the right movement
*/
public void correctMovementTest() {
Pawn p1 = new Pawn(Player.UP);
board.placePiece(4, 3, p1);
board.movePieceTo(5, 3, p1);
assertEquals(board.getPiece(5, 3), p1);
}
@Test
/**
* Testing the right movement
*/
public void correctMovementTest2() {
Pawn p1 = new Pawn(Player.UP);
board.placePiece(4, 3, p1);
board.movePieceTo(6, 3, p1);
assertEquals(board.getPiece(6, 3), p1);
}
....
如果我在testcase方法之外转换Board
和Pawn
p1
,那么它是否会起作用?为什么我们在测试类中需要@Before
?
此外,这样做不会起作用
@Before
public void setup() {
Board board = new Board();
Pawn p1 = new Pawn(Player.UP);
}
我认为这实际上会在测试用例之前设置对象,这样我就不必在每个测试用例中设置它们,但是测试用例实际上并不会读取p1对象和板。
答案 0 :(得分:5)
@Before
注释用于执行某些操作。所以,基本上你是在正确的方式。要使代码正常工作,您需要在功能范围之外声明Board
和Pawn
。
Board board = null;
Pawn p1 = null;
@Before
public void setup() {
board = new Board();
p1 = new Pawn(Player.UP);
}
在执行整个测试套件之前,还有@BeforeClass
个注释可用于执行一些操作 - 例如启动嵌入式数据库。
希望它有所帮助!
答案 1 :(得分:1)
@Before
和@BeforeClass
对于设置测试使用的外围设备非常有用。 @Before
将在每次测试之前运行,而@BeforeClass
将在测试套件之前运行(例如,在所有测试之前运行一次。)
让我们说你的测试都有一些常见的设置需要在运行之前完成。你可以总是只创建某种实用方法setup
,然后在每个类之前手动调用它:
private void setup() {
// do stuff
}
@Test
public void testFoo() {
setup();
// do test
}
@Test
public void testBar() {
setup();
// do test
}
...或者您可以使用setup
注释@Before
方法并让JUnit为您执行此操作:
@Before // JUnit will now call before every test, without you needing to do anything
public void setup() {
// do stuff
}
@Test
public void testFoo() {
// do test
}
@Test
public void testBar() {
// do test
}
@BeforeClass
注释在类似的概念下工作,除了它在整个套件之前挂钩并运行一次。
当我不得不模仿依赖时,我个人发现自己正在使用这些情况。
例如,考虑一个依赖于数据库连接的类。在我的@Before
中,我将创建一个这个数据库连接的模拟实例,我的测试可以根据需要注入/使用它:
private DbConnector mockDb;
@Before
public void initMocks() {
mockDb = Mockito.mock(DbConnector.class);
}
如果我不介意我的测试共享同一个实例,我可以mockDb
静态并使用@BeforeClass
。
在您的特定情况下,您有Board
个实例。如果您希望测试共享同一个板 - 例如,在给定板上运行不同测试没有副作用 - 那么您可以使用@BeforeClass
创建新实例:
private static Board board;
@BeforeClass
public static void initBoard() {
board = new Board();
// other board init logic here
}
也许我们希望在任何地方共享相同的Board实例,但我们需要做一些清理或设置逻辑。然后我们可以使用@Before
和@After
来注释这些方法,以便在每个测试实例周围运行它们,以使电路板进入预期状态。
@Before
public void setupBoard() {
// setup logic, runs before each test (maybe puts the pieces where they should go for a new game?)
}
@After
public void resetBoard() {
// reset logic, runs after every test (maybe remove scores, resets mocks, etc?)
}
何时使用这些注释,以及使用哪些特定的注释确实依赖于测试的设计方式。例如,如果设置您的主板只是new Board();
而不是其他任何内容,那么您实际上并不需要@BeforeClass
方法,而只能使用变量。
答案 2 :(得分:1)
从技术上讲,在测试类中包含实例字段(声明加初始化)以及在@Before
方法中创建实例(仅将引用声明为实例字段)是相同的,即您的全局数据将可用于所有您的@Test
方法,因为JUnit会自动为每个@Test
方法运行创建一个测试类实例,因此@Before
不需要始终。
但是使用方法#1(声明加初始化都作为实例字段),您不必占用测试类实例创建和测试数据准备,同时保持关注点分离并根据阶段可视化过程是一个好主意,如, 创建测试类的实例 - >创建SUT实例(被测服务) - >准备SUT的测试数据 - >呼叫测试方法等...... (只是一个样本)。
@Before
方法是使用模拟框架的必要条件,因为模拟需要首先在@Before
方法中进行初始化,但这似乎不再是必需的。 See
您必须意识到,您提出的示例非常简单,而在企业应用程序中,要进行单元测试的类非常复杂,并且人们不希望通过测试数据准备来混淆其字段声明区域。
总而言之 - @Before
并非强制性原因 - 即如果您希望在创建测试类实例之后执行某些操作(如果该用例非常适合您的方案),则使用它,否则您就是免费准备您的测试数据作为实例字段。
答案 3 :(得分:-1)
以下是一个例子:
带注释的方法@Before
在每次调用@Test
那么我要解决的问题是将局部变量转换为字段。这样,每个测试方法都可以访问变量。
public class PawnTest { //The Test Class itself
Board board;
private Pawn p1;
@Before
public void setup() {
board = new Board();
p1 = new Pawn(Player.UP);
}
@Test
/**
* Testing the right movement
*/
public void correctMovementTest() {
board.placePiece(4, 3, p1);
board.movePieceTo(5, 3, p1);
assertEquals(board.getPiece(5, 3), p1);
}
@Test
/**
* Testing the right movement
*/
public void correctMovementTest2() {
board.placePiece(4, 3, p1);
board.movePieceTo(6, 3, p1);
assertEquals(board.getPiece(6, 3), p1);
}
@After
public void tearDown() {
p1 = null;
board = null;
}
添加拆卸,以便测试用例彼此独立。
编辑:将board
初始化移至setUp()