3

Factory Girl を使用することは、1000 以上のテストを行うプロジェクトではあまり実用的ではないため、モックの作成方法を学び始めました。特に何らかの自動化された継続的インテグレーションを行いたい場合は、すべてのテストでデータベースにアクセスすることはできません。

私のテスト:

    it "should return an URL with the desired security protocol" do
        p = Proposal.new
        p.expects(:status).returns(Proposal::PUBLISHED) #this should be invoked by public_url?
        p.expects(:public_url).returns("https://something")
        p.expects(:public_url).with(true).returns("https://something")
        p.expects(:public_url).with(false).returns("http://something")
        assert p.public_url.index("https") != nil
        assert p.public_url(true).index("https") != nil
        assert p.public_url(false).index("https") == nil
    end

上記のテストの方法:

def public_url(https = true)
    url = ""
    if self.published?
        # attepmt to find sluggable id
        id = sluggable_id
        url = (https ? "#{ENV['SSL_PROTOCOL']}://" : "http://") + 
            self.account.full_domain + "/view/" + id.to_s
    end

    return url
end 

def published?
    return self.status > UNPUBLISHED
end

しかし、これは私がテストを実行すると得られるものです:

unsatisfied expectations:
- expected exactly once, not yet invoked: #<Proposal:0x7fbd07e82a30>.status(any_parameters)

public_url呼び出すべきではありませんstatus()か?

そうでない場合、私がp.status自分自身を呼び出す必要がある場合、それp.public_url()は私が書いたロジックを完全に無視し、私が定義したものに厳密に従っていることを意味しませんexpectsか? それは単体テストにどのように役立ちますか? たぶん私は嘲笑の目的を理解していません。


アップデート:

@Philipの提案に従って、テストをこれに変更し、ActiveRecordのシェナニガンの必要性を取り除きました。

    it "should return an URL with the desired security protocol" do
        p = Proposal.new
        p.expects(:id).returns(1)
        p.expects(:status).returns(Proposal::PUBLISHED)
        p.expects(:account).returns(Account.new.stubs(:localhost))

        assert p.public_url.starts_with("https")
        assert p.public_url(true).starts_with("https")
        assert !p.public_url(false).starts_with("https")
    end

私の質問は、フィクスチャ (私が名前を付けたもの) を使用してアカウントをスタブ化するにはどうすればよいかということだと思いますlocalhost。エラーが発生します:undefined method 'full_domain' for Mocha::Expectation:しかし、フィクスチャは次のように定義されています。

localhost:
  id: 1
  name: My first account
  full_domain: test.domain.vhost

すべてのテストで簡単に使用できるように、よくアクセスされるモデルの非常に基本的なものを使用できるように、フィクスチャをセットアップしました。すべてのテストの標準モデル/関係 (私が手作業で/工場の女の子でモックなしでテストを行う場合、これが必要になります: Account, Subscription(has Account, SubscriptionPlan), SubscriptionPlan, User(belongs to Account), AccountProperties(has Account), そして実際のオブジェクト私がテストしているのは、 anAccountと a Useron thatに属しておりAccount、これはすべてのテストで少し多めです。笑


更新 2:

うまくいきました:

it "should return an URL with the desired security protocol" do
            p = Proposal.new({:status => Proposal::PUBLISHED})
            p.expects(:id).returns(1)
            p.expects(:account).returns(accounts(:localhost)).times(3)

            assert p.public_url.starts_with?("https")
            assert p.public_url(true).starts_with?("https")
            assert !p.public_url(false).starts_with?("https")
        end

accounts、またはのようなフィクスチャにアクセスしますusers

4

1 に答える 1

1

私の理解では、あなたの 3p.expects(:public_url)...行はそのメソッドをスタブ化して、返すように指示した値を返しているということです。したがって、メソッド本体が呼び出されることはありません...スタブが引き継がれます。したがって... への呼び出しも期待するように言ったのでstatus、それは決して起こりません。

self.account.full_domainあなたのコードを見てください...あなたがスタブしたいのは、おそらくid.to_sこの行にあると思います:

url = (https ? "#{ENV['SSL_PROTOCOL']}://" : "http://") + 
            self.account.full_domain + "/view/" + id.to_s

これにより、AR 関係はスキップされますが、メソッドの残りの条件は実行されます。

また..私はあなたの主張を変更します。以下は、「http://https.com/blahblah」のような安全でない URL にも一致しますが、これは本当に必要なものではありません。他のものも合格する可能性がありますが、同様に無効な理由があります。

assert p.public_url(true).index("https") != nil

だから多分次のようなもの:

assert p.public_url(true).starts_with("https://") true

または、結果を取得してURIを使用して解析し、スキームを直接テストします(おそらくやり過ぎの考えです)

于 2013-01-06T02:58:46.370 に答える