Khẳng định một đối tượng là một loại cụ thể


195

JUnit có thể khẳng định một đối tượng là một thể hiện của một lớp không? Vì nhiều lý do tôi có một đối tượng trong bài kiểm tra của mình mà tôi muốn kiểm tra loại. Nó là một loại Object1 hay một loại Object2?

Hiện tại tôi có:

assertTrue(myObject instanceof Object1);
assertTrue(myObject instanceof Object2);

Điều này hoạt động nhưng tôi đã tự hỏi nếu có một cách biểu cảm hơn để làm điều này.

Ví dụ như một cái gì đó như:

assertObjectIsClass(myObject, Object1);

Tôi có thể làm điều này:

assertEquals(myObject.class, Object1.getClass());

Có một phương pháp khẳng định cụ thể nào cho phép tôi kiểm tra một loại đối tượng một cách thanh lịch, trôi chảy hơn không?


15
Bạn có biết rằng assertTrue(myObject instanceof Object1);assertEquals(myObject.class, Object1.getClass());thực sự là các bài kiểm tra khác nhau? Cái đầu tiên chấp nhận myObject là một thể hiện của một lớp con Object1, cái sau không.
Erich Kitzmueller

@ammoQ Điểm rất tốt. Tôi không nghĩ về các lớp con. Cảm ơn đã làm rõ
RNJ

1
như maba chỉ ra, hãy cân nhắc sử dụng Hamcrest. Điều này là nhiều hơn chỉ để bạn có một bài kiểm tra làm việc tốt hơn. Hamcrest cũng cung cấp đăng nhập thất bại tốt hơn nhiều so với tiêu chuẩn assertTrue. assertTruesẽ chỉ nói expected true got false, Hamcrest sẽ nóiexpected instanced of XYZ, got instance of ABC
John B

Câu trả lời:


253

Bạn có thể sử dụng assertThatphương thức và Trình so khớp đi kèm với JUnit.

Hãy xem liên kết này mô tả một chút về Bộ so khớp JUnit.

Thí dụ:

public class BaseClass {
}

public class SubClass extends BaseClass {
}

Kiểm tra:

import org.junit.Test;

import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertThat;

/**
 * @author maba, 2012-09-13
 */
public class InstanceOfTest {

    @Test
    public void testInstanceOf() {
        SubClass subClass = new SubClass();
        assertThat(subClass, instanceOf(BaseClass.class));
    }
}

4
Đây là liên kết đến Trình so khớp
John B

3
FYI, MatcherAssert.assertThat hoạt động tốt hơn (cung cấp đăng nhập tốt hơn trong trường hợp có lỗi) so với Assert.assertThat. Tôi khuyên bạn nên sử dụng nó thay thế. hamcrest.org/Javaoutcrest/javadoc/1.3/org/hamcrest/ory
John B

13
Đó là một khẳng định tầm thường và sẽ là một lỗi biên dịch nếu không đúng trong ví dụ! Thông thường bạn muốn đi xuống hệ thống phân cấp lớp với instanceof: BaseClass subClass = new SubClass(); assertThat(subClass, isA(SubClass.class));, nhưng nó không biên dịch vì SubClasskhông phải ? super BaseClass.
TWiStErRob

3
@TWiStErRob Tôi không hiểu bạn đang cố nói gì ở đây ... Hãy thử thay đổi instanceOf(BaseClass.class)thành instanceOf(String.class)và bạn sẽ thấy rằng nó biên dịch tốt nhưng sẽ có một Ass AssError bị ném.
maba

1
@maba, anh ấy đang nói về isA vì một số lý do, trong đó nắm bắt được lớp, nó chấp nhận Class<T>thay vì Class<?>(đó là những gì instanceOf làm). Vì nó nắm bắt được lớp, nên sẽ xảy ra lỗi biên dịch thời gian để thực hiện isA với một lớp không tương thích với thể hiện. github.com/hamcrest/Javaoutcrest/issues/39
Vsevolod Golovanov

46

assertThatđó là câu trả lời cũ hiện không được chấp nhận, tôi đang đăng giải pháp chính xác:

assertTrue(objectUnderTest instanceof TargetObject);


2
Nếu objectUnderTest là một lớp con của TargetObject, điều này vẫn sẽ dẫn đến trueđúng không? Và tôi nghĩ rằng bạn muốn thử nghiệm loại thực tế.
EricG

Tôi cảm thấy đây KHÔNG phải là câu trả lời chính xác. Câu hỏi ban đầu là yêu cầu một cái gì đó đặc biệt kiểm tra loại chính xác của đối tượng. Giải pháp này không phải như vậy (như đã đề cập bởi @EircG ở trên) và nó thậm chí còn được cung cấp bởi người dùng ban đầu đặt câu hỏi, vì vậy chắc chắn không phải là câu trả lời "đúng". Để có câu trả lời đúng, vui lòng kiểm tra câu trả lời của Franklin Yu.
kekko12

Chà, nó có nhược điểm mà @EricG đã đề cập là có, về câu trả lời của Franklin - Tôi chỉ nhìn vào nó, và nó không có ý nghĩa gì với tôi nên tôi đã thử nghiệm trong dự án của mình với Junit5 - thật sai lầm !! không có cú pháp như vậy cho instanceof, cũng không phải là một phương thức gọi là InstanceOf! Anh ấy hoàn toàn sai. Tôi vẫn đứng trước câu trả lời của mình và bằng chứng là nó hữu ích cho ít nhất 30 người đã ủng hộ nó! (Tôi giả sử bạn bị hạ thấp).
Carmageddon

@ kekko12 Câu trả lời của tôi không kiểm tra loại chính xác; nó chấp nhận lớp con tương tự như câu trả lời này. Tôi đã cập nhật câu trả lời của tôi để giải quyết nó; xin lỗi vì tôi đã không nhận thấy phần này trong câu hỏi. Tôi nghĩ rằng sự bình đẳng chính xác không được bao gồm trong hầu hết các thư viện khẳng định bởi vì nó không được sử dụng thường xuyên.
Franklin Yu

@Carmageddon Câu trả lời từ Franlin Yu không hoạt động tốt nếu bạn sử dụng nhập xác nhận hamcrest: `` `nhập tĩnh org.hamcrest.CoreMatchers.instanceOf; `` `ss trên mỗi mẫu mã của mình. Tôi thừa nhận mặc dù tôi đã bỏ qua câu trả lời của Franklin và trên thực tế, 2 câu trả lời này tương đương về chức năng, vì vậy tôi đoán đó chỉ là vấn đề ưu tiên cuối cùng.
kekko12

21

Giải pháp cho JUnit 5

Các tài liệu nói:

Tuy nhiên, org.junit.jupiter.Assertionslớp của JUnit Jupiter không cung cấp một assertThat()phương thức giống như phương thức được tìm thấy trong org.junit.Assertlớp của JUnit 4 chấp nhận Hamcrest Matcher. Thay vào đó, các nhà phát triển được khuyến khích sử dụng hỗ trợ tích hợp cho các công cụ đối sánh được cung cấp bởi các thư viện xác nhận của bên thứ ba.

Ví dụ cho Hamcrest :

import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.MatcherAssert.assertThat;

import org.junit.jupiter.api.Test;

class HamcrestAssertionDemo {

    @Test
    void assertWithHamcrestMatcher() {
        SubClass subClass = new SubClass();
        assertThat(subClass, instanceOf(BaseClass.class));
    }

}

Ví dụ cho AssertJ :

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;

class AssertJDemo {

    @Test
    void assertWithAssertJ() {
        SubClass subClass = new SubClass();
        assertThat(subClass).isInstanceOf(BaseClass.class);
    }

}

Lưu ý rằng điều này giả định rằng bạn muốn kiểm tra các hành vi tương tự instanceof(chấp nhận các lớp con). Nếu bạn muốn loại chính xác bằng nhau, tôi không thấy cách nào tốt hơn là khẳng định hai lớp bằng nhau như bạn đã đề cập trong câu hỏi.


1
Theo một nghĩa nào đó, bản gốc assertThat()được chuyển đến Hamcrest, do đó JUnit cũng hoạt động với các thư viện xác nhận của bên thứ ba.
Franklin Yu

Tôi vừa kiểm tra câu trả lời này, nó KHÔNG chính xác và dẫn đến nhiều lỗi biên dịch: Bắt đầu biểu hiện bất hợp pháp, bắt đầu bất hợp pháp loại, ';' mong đợi ... Nói cách khác, tham số thứ hai của bạn cho trình so khớp assertThat, CANNOT là "instanceof (BaseClass. class)"! Trên thực tế, bạn thậm chí không gõ đúng, cú pháp bạn đã sử dụng hơi khác một chút - "InstanceOf (" - như một lệnh gọi hàm! Thực sự không có chức năng nào như vậy ... nó thậm chí còn được kiểm tra bởi ai? đánh máy mà không có bất kỳ bài kiểm tra nào
Carmageddon

@Carmageddon Tôi đã cung cấp hai câu trả lời, một cho Hamcrest và một cho AssertJ. Bạn đang nói về cái nào?
Franklin Yu

@Carmageddon Tôi nghi ngờ rằng bạn đang nói về ví dụ Hamcrest và bạn đã gõ sai instanceOfnhư instanceof(nhớ trường hợp). instanceOfmột hàm trong khi instanceofmột từ khóa Java .
Franklin Yu

Tất nhiên, tôi đã đề cập đến Hamcrest và tôi đã thử cả từ khóa VÀ như một chức năng sau khi tôi nhận thấy đó là cách bạn viết nó - không có chức năng nào như vậy ...
Carmageddon

3

Giải pháp cho JUnit 5 cho Kotlin!

Ví dụ cho Hamcrest :

import org.hamcrest.CoreMatchers
import org.hamcrest.MatcherAssert
import org.junit.jupiter.api.Test

class HamcrestAssertionDemo {

    @Test
    fun assertWithHamcrestMatcher() {
        val subClass = SubClass()
        MatcherAssert.assertThat(subClass, CoreMatchers.instanceOf<Any>(BaseClass::class.java))
    }

}

Ví dụ cho AssertJ :

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class AssertJDemo {

    @Test
    fun assertWithAssertJ() {
        val subClass = SubClass()
        assertThat(subClass).isInstanceOf(BaseClass::class.java)
    }

}

1
Cảm ơn giải pháp assertJ rất thanh lịch này
Aleks Nine
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.