Java 在Junit测试中使用@Before

Java 在Junit测试中使用@Before,java,junit,Java,Junit,JUnit测试中需要使用@Before符号,因为一些测试需要在运行之前创建类似的对象 但是我不明白在testcase函数之前实例化一个对象作为全局对象和在之前放入一个@之间的区别 例如,我正在测试我的国际象棋程序,我正在测试我的棋子对象是否移动到正确的位置,方法是: public class PawnTest { //The Test Class itself Board board = new Board(); @Test /** * Testing the right movement

JUnit测试中需要使用
@Before
符号,因为一些测试需要在运行之前创建类似的对象

但是我不明白在testcase函数之前实例化一个对象作为全局对象和在之前放入一个
@之间的区别

例如,我正在测试我的国际象棋程序,我正在测试我的棋子对象是否移动到正确的位置,方法是:

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
public void setup() {
    Board board = new Board();
    Pawn p1 = new Pawn(Player.UP);
}
我认为这实际上会在测试用例之前设置对象,这样我就不必在每个测试用例上都设置它们,但是测试用例实际上不会读取p1对象和电路板。

下面是一个示例:

在每次调用
@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()

注释用于在类中执行每个测试用例之前执行某些操作。所以,基本上你走对了路。要使代码正常工作,您需要将
典当
声明在功能范围之外

Board board = null;
Pawn p1 = null;

@Before
public void setup() {
    board = new Board();
    p1 = new Pawn(Player.UP);
}
还有一个注释可用于在执行整个测试套件之前执行一次某些操作,例如启动嵌入式数据库。
希望有帮助

@Before
@BeforeClass
对于设置测试使用的外围设备非常有用
@Before
将在每次测试之前运行,而
@BeforeClass
将在测试套件之前运行(例如在所有测试之前运行一次)

假设您的测试都有一些在运行之前需要完成的公共设置。您始终可以创建某种实用程序方法
setup
,然后在每个类之前手动调用它:

private void setup() {
  // do stuff
}

@Test
public void testFoo() {
  setup();
  // do test
}

@Test
public void testBar() {
  setup();
  // do test
}
。。。或者,您可以在
之前使用
@注释
设置
方法,并让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
}
也许我们想在任何地方共享同一个电路板实例,但我们需要执行一些清理或设置逻辑。然后,我们可以在每个测试实例周围使用
@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?)
}

何时使用这些注释,以及使用哪些特定注释实际上取决于测试的设计方式。例如,如果设置板只是
newboard()之外,您并不真正需要
@BeforeClass
方法,您可以只使用一个变量。

从技术上讲,在测试类中有实例字段(声明和初始化),并在
@Before
方法中创建实例(仅引用声明为实例字段)都是一样的,也就是说,由于JUnit会自动为每个运行的
@Test
方法创建一个测试类实例,所以
@Before
并不总是需要
@Test
方法,所以您的全局数据将对所有
@Test
方法可用

但是使用方法#1(声明和初始化都作为实例字段),您不必将测试类实例创建和测试数据准备捆绑在一起,同时将关注点分开,并根据阶段可视化过程是一个好主意,如,创建测试类实例->创建SUT实例(测试中的服务)->为SUT准备测试数据->调用测试方法等。(只是一个示例)

@Before
方法对于使用模拟框架也是必要的,因为模拟需要首先在
@Before
方法中初始化,但这似乎不再是必要的

您必须认识到,您提出的示例非常简单,而在企业应用程序中,要进行单元测试的类非常复杂,人们不希望在准备测试数据时将字段声明区域弄得杂乱无章


总而言之,
之前的
@不是强制性的,因为有一个原因-即,如果您希望在创建测试类实例之后做某些事情,您可以使用它(如果该用例确实适合您的场景)否则,您可以自由地将测试数据准备为实例字段。

P1是一个局部变量。将其作为成员变量。请阅读有关变量范围的更多信息。那么,我应该如何设置它以防止重复代码?在编辑代码时,可能会重复代码,请为此代码添加一些上下文。代码转储答案对任何人都没有用处EST现在也相互依赖,因为它们共享同一个董事会。-啊,刚刚看到这已经是OPs中的一个问题question@Absurd-注意:我不认为是这样。如果我错了,请纠正我。p1在每次测试运行时都会重新初始化。@NewUser,但板在PawnTest初始化时只初始化一次。sam