我正在嘗試進行一些依賴注入以進行單元測驗,并使 iOS 實時預覽更容易。
我有一個Store協議,我想在我的 SUT 類中使用它們,這樣我就可以傳遞模擬實作。
protocol Store {
associatedtype AnyData
func load() -> AnyData?
func save(data anyData: AnyData)
}
class FileStore<AnyData: Codable>: Store {
func load() -> AnyData? { /* Actual code that saves to a file */ }
func save(data anyData: AnyData) { /* Actual code that saves to a file */ }
}
class MockStore<AnyData: Codable>: Store {
func load() -> AnyData? { /* Returns mocked value for unit testing */ }
func save(data anyData: AnyData) { /* Returns mocked value for unit testing */ }
}
但是,在我的 SUT 課程中,我有以下內容:
class MyClassToBeTested {
// THIS DOESN'T WORK
let bookStore: Store // ERROR: Protocol 'Store' can only be used as a generic
// constraint because it has Self or associated type requirements
// DOESN'T WORK EITHER
let studentStore: Store<Student> // ERROR: Cannot specialize non-generic type 'Store'
}
// in real app
MyClassToBeTested(
bookStore: FileStore<Book>()
studentStore: FileStore<Student>()
)
// in test or preview
MyClassToBeTested(
bookStore: MockStore<Book>()
studentStore: MockStore<Student>()
)
好像我被卡住了。我本質上是在嘗試擁有一個通用協議,類似于 Java 中的通用介面。我錯過了什么?
更新
在@Jessy 回答之后,我做到了:
class MyClassToBeTested<BookStore: Store, StudentStore: Store>
where
BookStore.AnyData == Book,
StudentStore.AnyData == Student
{
let bookStore: BookStore
let studentStore: StudentStore
這解決了一半的問題。另一半是如何使用它鍵入變數:
class OtherClass {
var sut: MyClassToBeTested // ERROR: Generic parameter Bookstore could not be inferred
var sut2: MyClassToBeTested< // I know this isn't supported in Swift
Store<Book>, // but can't figure out the right syntax
Store<Student> // ERROR: Cannot specialize non-generic type 'Store'
> // ERROR: Protocol 'Store' as a type cannot conform to the protocol itself
var sut3: MyClassToBeTested< // Compiles, BUT I cannot pass a
FileStore<Book>, // MockStore in my tests/preview
FileStore<Student> // so it's useless
>
}
uj5u.com熱心網友回復:
該
Store<Student>語法從未得到支持,但最近 Swift 論壇上有很多關于它的討論——可能很快就會支持。Stack Overflow 上還有許多其他關于無法使用具有關聯型別(如存在)的協議的 Q/A——它終于可用,但僅在 Xcode 13.3(測驗版)中可用。
在我看來,您希望事情受到這樣的限制:
class MyClassToBeTested<BookStore: Store, StudentStore: Store>
where
BookStore.AnyData == Book,
StudentStore.AnyData == Student
{
let bookStore: BookStore
let studentStore: StudentStore
如果沒有,從 Xcode 13.3 開始可用的最新語法是
class MyClassToBeTested<StudentStore: Store>
where StudentStore.AnyData == Student {
let bookStore: any Store
let studentStore: StudentStore
init(
bookStore: any Store,
studentStore: StudentStore
) {
self.bookStore = bookStore
self.studentStore = studentStore
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/429702.html
