2016-07-15 13 views
1

私はちょうどJavaアプリケーション用のSpockテストフレームワークの作業を開始しました。以前Groovyの経験はありませんでした。 Spockフレームワークを使用してコンストラクタにモックを挿入するにはどうすればよいですか?以下は私のコードとテストの例です。モックオブジェクトをコンストラクタに挿入するにはどうすればいいですか?

public class ResourceClass { 
    private final IDynamoDBMapper factory = new DefaultDynamoDBClientFactory(DynamoDBConfig.fromProperties()).mapperClient(); 

    private ServiceClass service; 

    @Inject 
    public ResourceClass(ServiceClass service) { 
     this.service = service; 
    } 
} 

そして、以下のようなテストクラスを作成しようとしました。

class ResourceClassTest extends Specification { 
ResourceClass eventsResource 
ServiceClass service 

def setup() { 
    service = Mock(ServiceClass) 
    eventsResource = new ResourceClass(service) 
} 

しかし、私はeventsResource =新しいResourceClass(サービス)

java.lang.NullPointerException: Domain name must be specified. 

at java.util.Objects.requireNonNull(Objects.java:228) 

で例外の下に任意の提案を取得していますしてください?

答えて

1

モックで渡すコンストラクタを呼び出すだけであるので、問題はResourceClassのコンストラクタにモックを '注入'することではありません。この例外が発生した理由は、このフィールド宣言+ initialiazationである:工場出荷時のフィールドの

private final IDynamoDBMapper factory = new DefaultDynamoDBClientFactory(DynamoDBConfig.fromProperties()).mapperClient(); 

の初期化は、コンストラクタが実行される前に(それは実際には、コンパイル時にコンストラクタの先頭にコピーされます)発生します。

DynamoDBConfig.fromProperties()がどのように動作し、dynamo db接続のドメインプロパティが指定されるべきかを確認するなど、工場の初期化に失敗した理由を確認するか、ファクトリオブジェクトをリソースクラスに注入するようにソースコードを変更できますかあなたがサービスを行うのと同じ方法では、コンストラクタで、その後の試験で、サービスコンストラクタにIDynamoDBMapperのモックを渡します

public class ResourceClass { 
    private final IDynamoDBMapper factory; 
    private ServiceClass service; 

    @Inject 
    public ResourceClass(ServiceClass service, IDynamoDBMapper factory) { 
     this.service = service; 
     this.factory = factory; 
    } 
} 

class ResourceClassTest extends Specification { 
    ResourceClass eventsResource 
    ServiceClass service 
    IDynamoDBMapper mapper 

    def setup() { 
     service = Mock(ServiceClass) 
     mapper = Mock(IDynamoDBMapper) 
     eventsResource = new ResourceClass(service, mapper) 
    } 
} 

[リソースクラスをテストする上でより多くの制御を得る第二の溶液ではなく、最初の解決策はより簡単になるはずです

+0

はあなたにGergelyをありがとうございます。 DynamoDBMapperをリソースクラスに挿入するようにソースコードを変更しました。これは、Spockを使用する場合、またはmockitoを使用する場合にのみ発生します。 – vamsi

+0

これはSpockテストを実行しているときに発生しますが、スポークの問題ではありませんが、アプリケーションを実行するときとテストを実行するときにクラスパスが異なることがあります。したがって、アプリケーションを実行しているときにclasspathにdynamo db設定ファイルがあり、テストを実行していない場合 –

1

Eit彼女はあなたのDefaultDynamoDBClientFactory.mapperClient()を何とか模倣するか、注射可能にする必要があります。そうしないと、実際のインスタンシエーションを探して失敗します。

public class ResourceClass { 
    private IDynamoDBMapper factory; 
    private ServiceClass service; 

    @Inject 
    public ResourceClass(IDynamoDBMapper factory, ServiceClass service) { 
     this.factory = factory; 
     this.service = service; 
    } 
} 

その後、あなたは以下のように派手な方法であなたのresourceClassをテストユニットのことができるようにする必要があり、

class ResourceClassSpec extends Specification { 
    ResourceClass eventsResource 

    def setup() { 
     eventsResource = new ResourceClass(factory: Mock(IDynamoDBMapper), service: Mock(ServiceClass)) 
    } 

    def 'test does something'() { 
     given: 'given x' 
      // 
     when: 'when you call some method of resourceClass' 
      // 
     then: 'what you expect' 
      // 
      1 == 2 
    } 
} 
関連する問題