2016-09-21 5 views
1

私はRspecにはかなり新しく、オブジェクトをコンストラクタパラメータとして受け取り、クラスを設定するクラスのテストを書く方法を理解しようとしていますそのオブジェクトをインスタンス変数に追加します。次に、他のメソッドでそのインスタンス変数のオブジェクトメソッドを呼び出します。インスタンス変数としてgemオブジェクトを使用するクラスのRSpecテスト

例:

class ClassA 
    def initialize(string_object, gem_object) 
    @instance_variable1 = gem_object 
    @string = string_object 
    end 

    def check_validity?(some_arg) 
    unless @instance_variable1.gemObjectMethod1.gemObjectMethod2(some_arg).empty? 
     return true 
    end 
    false 
    end 
    .. 
    .. 
end 

私は非常にこの仕様を記述する方法で失われた感じ。私は実際にはコンストラクタを指定するのは実際には何を意味するのか分かりません。私が気づいているのは、私が議論の対象としているgem_objectを嘲笑したりスタブしたりする何らかの方法を見つけなければならないということです。

describe '#check_validity?' do 
    context 'gets empty list' do 
    let (:actual) { subject.check_validity?("sample") } 
    before do 
     allow(subject).to receive(@instance_variable1.gemObjectMethod1.gemObjectMethod2).with("sample").and_return([]) 
    end 
    it 'returns false' do 
     expect(actual).to be false 
    end 
    end 
end 

しかし、これは、それは2つの引数を期待しますが

0を与えられたと言って私のコンストラクタに関連する私にエラーを与える:

次の方法については

、私はこのポイントにしようとしたものですどんな助けでも大歓迎です!また、私は実際に引数が偽装されたコンストラクタを指定することについて、オンライン上で何も見つけることができませんでした。たぶん私は間違った場所を探しているか、これがBDDの私の最初の経験であるため、明らかなものがないかもしれません。

答えて

1

RSpecでは、 'receive'はメソッドの名前を表すシンボルを受け入れるメソッドです。 (これは、パラメータの予想されるリストを受け取るメソッド「と」A鎖にことができます。)あなたがこれを行うことができます前に、ブロック修正するには:

before do 
    allow(subject.instance_variable_get(:@instance_variable1).gemObjectMethod1).to receive(:gemObjectMethod2).with("sample").and_return([]) 
end 

その薄手の醜さ、しかし、何かがあることを示唆しています違う。それはそうです。コードがlaw of demeterに悪い影響を与えており、そのテストはその中に取り込まれています。

最初の試みでは、@ instance_variable1.gemObjectMethod1を呼び出した結果をキャッシュする方法が考えられます。最初のメソッドが、列挙可能なウィジェットのグループを返すとしましょう。あなたはこのようなものを含めるようにクラスを変更することができます:

def check_validity(a_string) 
    widgets.gemObjectMethod2(a_string).empty? 
end 

private 

def widgets 
    @widgets ||= @instance_variable1.gemObjectMethod1 
end 

は、あなたのクラスはまだ宝石のオブジェクトについて少しあまりにも多くを知っているが、今、あなたはあなたがウィジェットを見つける方法をリファクタリング可能性があり、このような方法でそれを分解しています - おそらく別の宝石やあなた自身のそれの実装。あなたのテストの目的のために、あなたはウィジェットを模倣することによってテストからその決定を分離することができます。

let(:gem_widgets) do 
    instance_double(GemObjectMethod1ResultClass, gemObjectMethod2: true) 
end 

before do 
    allow(subject).to receive(:widgets).and_return(gem_widgets) 
    allow(gem_widgets).to receive(:gemObjectMethod2).with("sample"). 
    and_return([]) 
end 

it 'should pass with "sample"' do 
    expect(actual).to eql true 
end 
+0

ありがとうございました。あなたはコンストラクタをテストする方法についての提案がありますか?私は、オブジェクトがnewを呼び出す前に存在していないことをテストし、その後、それが正しいインスタンス変数を持つことを考えていました。私はオブジェクトが作成されているかどうかをテストする方法については空白です。 – marauder7

+0

私がよくこのようなクラスで行うことは、属性リーダー(例えば、attr_reader:string_object、:ClassAの最上部にあるgem_object)を通じてインスタンス変数を利用できるようにすることです。その場合、代入のテストは非常に簡単です。インスタンス化後にgetterメソッドの値を確認してください。 – AndyV

+0

ありがとうございます。私はしかし、質問があります。ウィジェットメソッドを作成することで、gemObjectMethod1が返すものを正確に見つけ出す必要はありませんし、抽象化の原則に反するものではありませんか? – marauder7

関連する問題