Cách thực hiện kiểm tra instanceof với Scala (Test)


100

Tôi đang cố gắng kết hợp ScalaTest vào dự án Java của mình; thay thế tất cả các bài kiểm tra JUnit bằng ScalaTests. Tại một thời điểm, tôi muốn kiểm tra xem Guice's Injector có tiêm đúng loại không. Trong Java, tôi có một bài kiểm tra như sau:

public class InjectorBehaviour {
    @Test
    public void shouldInjectCorrectTypes() {
        Injector injector = Guice.createInjector(new ModuleImpl());
        House house = injector.getInstance(House.class);

        assertTrue(house.door() instanceof WoodenDoor);
        assertTrue(house.window() instanceof BambooWindow);
        assertTrue(house.roof() instanceof SlateRoof);
    }
}

Nhưng tôi gặp sự cố khi làm tương tự với ScalaTest:

class InjectorSpec extends Spec {
    describe("An injector") {
        it("should inject the correct types") {
            val injector = Guice.createInjector(new ModuleImpl)
            val house = injector.getInstance(classOf[House])

            assert(house.door instanceof WoodenDoor)
            assert(house.window instanceof BambooWindow)
            assert(house.roof instanceof SlateRoof)
        }
    }
}

Nó phàn nàn rằng giá trị instanceofkhông phải là thành viên của Door/ Window/ Roof. Tôi không thể sử dụng instanceofcách đó trong Scala?

Câu trả lời:


114

Scala không phải là Java. Scala chỉ không có toán tử instanceofthay vào đó nó có một phương thức tham số được gọi isInstanceOf[Type].

Bạn cũng có thể thích xem một Khóa học về sự cố ScalaTest .


6
tốt, điều đó không thực sự trả lời câu hỏi. ScalaTest có hỗ trợ tích hợp để kiểm tra kiểu. Xem câu trả lời từ @ martin-g
maasg

Làm thế nào để làm điều đó nếu "Loại" đó là một đặc điểm?
Lobo

Bạn không chắc chắn nếu tôi hiểu đúng, nhưng nó phải là như nhau: isInstanceOf[TraitName].
agilesteel

88

Với Scalatest 2.2.x (thậm chí có thể sớm hơn), bạn có thể sử dụng:

anInstance mustBe a[SomeClass]

4
Đây là cách tiếp cận được đề xuất trên các phiên bản gần đây của ScalaTests
maasg 07-06-2016

6
cũng có sẵn a[Type]để bạn có thể đúng ngữ pháp;)
Samuel

Tôi đã tìm kiếm điều đó! :)
Atais

22
tiger shouldBe a [Tiger]là cú pháp hiện tại scalatest.org/at_a_glance/FlatSpec
jhegedus

2
@jhegedus mustBecũng đúng, nếu bạn sử dụng doc.scalatest.org/3.0.1/#org.scalatest.MustMatchers mà bạn muốn cho FreeSpec.
Tobi

30

Nếu bạn muốn ít JUnit-esque hơn và nếu bạn muốn sử dụng trình đối sánh của ScalaTest, bạn có thể viết trình đối sánh thuộc tính của riêng bạn phù hợp với loại (tẩy xóa kiểu thanh).

Tôi thấy chủ đề này khá hữu ích: http://groups.google.com/group/scalatest-users/browse_thread/thread/52b75133a5c70786/1440504527566dea?#1440504527566dea

Sau đó, bạn có thể viết các xác nhận như:

house.door should be (anInstanceOf[WoodenDoor])

thay vì

assert(house.door instanceof WoodenDoor)

+1 Điều đó trông rất đẹp, và thậm chí có thể hiểu được đối với những người không phải lập trình (giả sử họ biết thể hiện là gì :-)).
helpermethod 19/12/11

Nếu cú ​​pháp đường là những gì bạn đang theo đuổi, với một số cấu trúc lại, bạn có thể viết house.door nên là (madeOf [Wood]) hoặc house.door nên là (madeOf [Bamboo]).
Guillaume Belrose,


16

Các câu trả lời hiện tại về isInstanceOf [Loại] và lời khuyên dành cho junit là tốt nhưng tôi muốn bổ sung một điều (đối với những người đã truy cập trang này với tư cách không liên quan đến junit). Trong nhiều trường hợp, kết hợp mô hình tỷ lệ sẽ phù hợp với nhu cầu của bạn. Tôi muốn giới thiệu nó trong những trường hợp đó vì nó cung cấp cho bạn đánh máy miễn phí và ít có chỗ cho lỗi hơn.

Thí dụ:

OuterType foo = blah
foo match {
  case subFoo : SubType => {
    subFoo.thingSubTypeDoes // no need to cast, use match variable
  }
  case subFoo => {
    // fallthrough code
  }
}

Cách được khuyến nghị để kiểm tra đối sánh mẫu trong ScalaTest là sử dụng inside(foo)thay vì `foo match). Xem scalatest.org/user_guide/using_matchers#matchingAPattern
Rich Dougherty

3

Hợp nhất tài liệu tham khảo thảo luận ScalaTest của Guillaume (và một cuộc thảo luận khác được liên kết bởi James Moore) thành hai phương thức, được cập nhật cho ScalaTest 2.x và Scala 2.10 (để sử dụng ClassTag thay vì tệp kê khai):

import org.scalatest.matchers._
import scala.reflect._

def ofType[T:ClassTag] = BeMatcher { obj: Any =>
  val cls = classTag[T].runtimeClass
  MatchResult(
    obj.getClass == cls,
    obj.toString + " was not an instance of " + cls.toString,
    obj.toString + " was an instance of " + cls.toString
  )
}

def anInstanceOf[T:ClassTag] = BeMatcher { obj: Any =>
  val cls = classTag[T].runtimeClass
  MatchResult(
    cls.isAssignableFrom(obj.getClass),
    obj.getClass.toString + " was not assignable from " + cls.toString,
    obj.getClass.toString + " was assignable from " + cls.toString
  )
}

2

Tôi sử dụng 2.11.8 để thực hiện xác nhận với các bộ sưu tập. Cú pháp mới hơn như sau:

val scores: Map[String, Int] = Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8)
scores shouldBe a[Map[_, _]] 

3
Do tẩy xóa, bạn không thể kiểm tra các Mapthông số loại của. Những gì bạn đã viết cũng giống như viết scores shouldBe a[Map[_, _]]. Điều này được đề cập ở đây: scalatest.org/user_guide/using_matchers#checkingAnObjectsClass
Rich Dougherty
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.