2017-07-12 16 views
0

私はケーキのパターンを使用しているScalaのアプリを持っている:私は単純にconsumer.writeの実装をテストするために始めたときScalaMockとケーキパターン - 私のスタブはなぜ呼び出されませんか?

trait RepositoryComponent { 
    def repository: Repository 

    trait Repository { 
    def shouldSave(record: GenericRecord): Boolean 
    def findRecord(keys: Array[String]): Long 
    def insertRecord(record: GenericRecord) 
    def updateRecord(keys: Array[String], record: GenericRecord) 
    def cleanUp() 
    } 
} 

trait DbRepositoryComponent extends RepositoryComponent with Logged { 
    val connection: Connection 
    val subscription: Subscription 
    val schema: Schema 

    def repository = new DbRepository(connection, subscription, schema) 

    class DbRepository(connection: Connection, subscription: Subscription, schema: Schema) extends Repository { 
    ... 
    } 

trait ConsumerComponent { 
    def consumer: Consumer 

    trait Consumer { 
    def write(keys: Array[String], record: GenericRecord) 
    def close() 
    } 
} 

trait DbReplicatorComponent extends ConsumerComponent with Logged { 
    this: RepositoryComponent => 

    def consumer = new DatabaseReplicator() 

    class DatabaseReplicator extends Consumer { 
    ... 
    } 

、私は(ScalaMockを使用して)このような何かを試してみました:

class DbReplicatorComponentTests extends FunSuite with MockFactory { 

    private val schema = new Schema.Parser().parse(getClass.getResourceAsStream("/AuditRecord.avsc")) 
    private val record = new GenericRecordBuilder(schema) 
    .set("id1", 123) 
    .set("id2", "foo") 
    .set("text", "blergh") 
    .set("audit_fg", "I") 
    .set("audit_ts", 1498770000L) 
    .build() 

    test("A record should be inserted if the audit flag is 'I' and no existing record is found") { 
    val replicator = new DbReplicatorComponent with RepositoryComponent { 
     override def repository: Repository = stub[Repository] 
    } 

    (replicator.repository.shouldSave _).when(record).returns(true) 
    (replicator.repository.findRecord _).when(Array("123", "foo")).returns(0L) 

    replicator.consumer.write(Array("123", "foo"), record) 

    (replicator.repository.insertRecord _).verify(record) 
    } 
} 

Unsatisfied expectation: 

Expected: 
inAnyOrder { 
    <stub-1> Repository.shouldSave({"id1": 123, "id2": "foo", "text": "blergh", "audit_fg": "I", "audit_ts": 1498770000}) any number of times (never called) 
    <stub-2> Repository.findRecord([Ljava.lang.String;@4b8ee4de) any number of times (never called) 
    <stub-4> Repository.insertRecord({"id1": 123, "id2": "foo", "text": "blergh", "audit_fg": "I", "audit_ts": 1498770000}) once (never called - UNSATISFIED) 
} 

Actual: 
    <stub-3> Repository.shouldSave({"id1": 123, "id2": "foo", "text": "blergh", "audit_fg": "I", "audit_ts": 1498770000}) 
ScalaTestFailureLocation: com.generalmills.datalake.sql.DbReplicatorComponentTests at (DbReplicatorComponentTests.scala:12) 
org.scalatest.exceptions.TestFailedException: Unsatisfied expectation: 

この問題は、私は本当にないという事実を強調:私は実際の実装をスタブいないよので、テストが失敗していますスララではない。スタブ3がどこから来るのか分かりません。 this questionのdamirvの回答に続いて私のテストを正常に修正しましたが、私がここで望んでいることは、よりよく理解できるようになるための洞察です。私は実際に私が上記のテストをしていると思っています。

Fwiw、私はC#の背景からScalaに来る。

UPDATE:以下の回答に基づいて、この作品:

test("A record should be inserted if the audit flag is 'I' and no existing record is found") { 
    val replicator = new DbReplicatorComponent with RepositoryComponent { 
     val _repo = stub[Repository] 
     override def repository: Repository = { 
     _repo 
     } 
    } 

    (replicator.repository.shouldSave _).when(record).returns(true) 
    (replicator.repository.findRecord _).when(Array("123", "foo")).returns(0L) 

    replicator.consumer.write(Array("123", "foo"), record) 

    (replicator.repository.insertRecord _).verify(record) 
    } 

答えて

2

def repository: Repositoryこれは新しいスタブにあなたがそれを呼び出すたびに返すメソッドです。あなたは、パラメータの種類として配列を使用している、また

test("A record should be inserted if the audit flag is 'I' and no existing record is found") { 
    val replicator = new DbReplicatorComponent with RepositoryComponent { 
    override val repository: Repository = stub[Repository] 
    } 
    // ... 
} 

:すべての呼び出し/アクセスに同じスタブを返す代わりに、それval作ってみましょう。ここで説明するように、Unable to create stub with Array argument in ScalMock

するか、述語マッチングを試してください: - ScalaではArray("foo") != Array("foo")ので、私はあなたがアレイ(findRecord)を使用し、あなたのwhen呼び出しでargThatマッチャーを使用することをお勧めことに注意してくださいここを参照してください。もちろん、http://scalamock.org/user-guide/matching/

+0

- あなたがそれを指摘したのであまりにも明白です。 – Stuart

+0

valを使用しても問題ありませんか?その後、テストの実装を置き換えることができませんでした。 – Stuart

+0

'def'を' val'で上書きすることができます。したがって:特性の中では 'def'を使います。具体的なクラス/オブジェクトでは 'val'を使用し、それはうまくいくでしょう:) –

関連する問題