Tôi thiết lập một lớp với một vài bài kiểm tra và thay vì sử dụng, @Before
tôi muốn có một phương thức thiết lập chỉ thực thi một lần trước tất cả các bài kiểm tra. Điều đó có thể với Junit 4.8 không?
Tôi thiết lập một lớp với một vài bài kiểm tra và thay vì sử dụng, @Before
tôi muốn có một phương thức thiết lập chỉ thực thi một lần trước tất cả các bài kiểm tra. Điều đó có thể với Junit 4.8 không?
Câu trả lời:
Mặc dù tôi đồng ý với @assylias rằng việc sử dụng @BeforeClass
là một giải pháp cổ điển nhưng không phải lúc nào cũng thuận tiện. Phương thức được chú thích @BeforeClass
phải là phương thức tĩnh. Nó rất bất tiện cho một số thử nghiệm cần trường hợp thử nghiệm. Ví dụ: Kiểm tra dựa trên mùa xuân sử dụng @Autowired
để làm việc với các dịch vụ được xác định trong ngữ cảnh mùa xuân.
Trong trường hợp này, cá nhân tôi sử dụng setUp()
phương pháp thông thường được chú thích bằng @Before
chú thích và quản lý cờ static
(!) Tùy chỉnh của mình boolean
:
private static boolean setUpIsDone = false;
.....
@Before
public void setUp() {
if (setUpIsDone) {
return;
}
// do the setup
setUpIsDone = true;
}
setUp()
phương thức nằm trong lớp cha - đã đăng câu trả lời bên dưới để cố gắng giải quyết vấn đề này.
Bạn có thể sử dụng các BeforeClass
chú thích :
@BeforeClass
public static void setUpClass() {
//executed only once, before the first test
}
TheClassYouWant.class
thay thế cho lệnh gọi getClass () của mình? Đây là thực tế Java: String.class.getName()
.
JUnit 5 hiện có chú thích @BeforeAll:
Biểu thị rằng phương thức được chú thích phải được thực thi trước tất cả các phương thức @Test trong phân cấp lớp hoặc lớp hiện tại; tương tự như @BeforeClass của JUnit 4. Các phương thức như vậy phải tĩnh.
Các chú thích về vòng đời của JUnit 5 dường như cuối cùng đã hiểu đúng! Bạn có thể đoán chú thích nào có sẵn mà không cần nhìn (ví dụ: @BeforeEach @AfterAll)
@BeforeClass
, nó cần phải được static
. Giải pháp của IMO @ AlexR là tốt hơn.
Khi setUp()
ở trong lớp cha của lớp thử nghiệm (ví dụ: AbstractTestBase
bên dưới), câu trả lời được chấp nhận có thể được sửa đổi như sau:
public abstract class AbstractTestBase {
private static Class<? extends AbstractTestBase> testClass;
.....
public void setUp() {
if (this.getClass().equals(testClass)) {
return;
}
// do the setup - once per concrete test class
.....
testClass = this.getClass();
}
}
Điều này sẽ hoạt động đối với một setUp()
phương pháp không tĩnh duy nhất nhưng tôi không thể tạo ra một phương pháp tương đương tearDown()
mà không lạc vào một thế giới phản chiếu phức tạp ... Tiền thưởng chỉ cho bất kỳ ai có thể!
Chỉnh sửa: Tôi vừa phát hiện ra trong khi gỡ lỗi rằng lớp cũng được khởi tạo trước mỗi bài kiểm tra. Tôi đoán chú thích @BeforeClass là tốt nhất ở đây.
Bạn cũng có thể thiết lập trên phương thức khởi tạo, lớp kiểm tra xét cho cùng là một lớp. Tôi không chắc đó có phải là một thực hành xấu hay không vì hầu hết các phương pháp khác đều được chú thích, nhưng nó hoạt động. Bạn có thể tạo một hàm tạo như vậy:
public UT () {
// initialize once here
}
@Test
// Some test here...
Ctor sẽ được gọi trước khi kiểm tra vì chúng không tĩnh.
Hãy thử giải pháp này: https://stackoverflow.com/a/46274919/907576 :
với @BeforeAllMethods
/ @AfterAllMethods
annotation, bạn có thể thực thi bất kỳ phương thức nào trong lớp Test trong ngữ cảnh cá thể, nơi tất cả các giá trị được đưa vào đều có sẵn.
Giải pháp bẩn của tôi là:
public class TestCaseExtended extends TestCase {
private boolean isInitialized = false;
private int serId;
@Override
public void setUp() throws Exception {
super.setUp();
if(!isInitialized) {
loadSaveNewSerId();
emptyTestResultsDirectory();
isInitialized = true;
}
}
...
}
Tôi sử dụng nó như một cơ sở cơ bản cho tất cả các testCases của tôi.
Nếu bạn không muốn bắt buộc khai báo một biến được đặt và kiểm tra trên mỗi bài kiểm tra con, thì việc thêm điều này vào SuperTest có thể làm:
public abstract class SuperTest {
private static final ConcurrentHashMap<Class, Boolean> INITIALIZED = new ConcurrentHashMap<>();
protected final boolean initialized() {
final boolean[] absent = {false};
INITIALIZED.computeIfAbsent(this.getClass(), (klass)-> {
return absent[0] = true;
});
return !absent[0];
}
}
public class SubTest extends SuperTest {
@Before
public void before() {
if ( super.initialized() ) return;
... magic ...
}
}
Tôi đã giải quyết vấn đề này như thế này:
Thêm vào lớp trừu tượng Cơ sở của bạn (ý tôi là lớp trừu tượng nơi bạn khởi tạo trình điều khiển của mình trong phương thức setUpDriver () ) phần mã này:
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
Và bây giờ, nếu các lớp thử nghiệm của bạn mở rộng từ lớp trừu tượng Cơ sở -> phương thức setUpDriver () sẽ được thực thi trước @Test đầu tiên chỉ MỘT lần mỗi lần chạy.
Sử dụng phương thức @PostConstruct của Spring để thực hiện tất cả công việc khởi tạo và phương thức này chạy trước khi bất kỳ @Test nào được thực thi