9

例えば、以下のようなコードがあったとします。

module Foo
  def bar(i)
    i + 1
  end
end

class Bar
  attr_accessor :some_value
  include Foo
  def initialize(any_value)
    @some_value = bar(any_value)
  end
end

このとき、Fooは広範囲で使われるため、Barとしてのテストではなく、Foo自体のメソッドとしてテストしたいとします。このとき、考えうる方法は二つあるかと思われます。

まず一つにはObject.new.extend(Foo)で、Objectのインスタンスに対して、後付けする方法。

もう一つはインスタンスメソッドにすることを諦めて、self.barとして定義しなおす方法。

しかし、上記二つは、どちらも余り綺麗とは言えないような気がします。上記以外で、Moduleで定義され、インスタンスメソッドとして利用されることを期待されるメソッドをテストするための、もっとスマートな方法があれば教えて下さい。

Yuki Inoue
  • 16,805
  • 19
  • 80
  • 196
esehara
  • 1,383
  • 1
  • 13
  • 26

3 Answers3

10

Fooモジュールをincludeしたクラスを作成し、そのクラスのインスタンスに対してテストするとよいのではないでしょうか。

例えばClass.newを使うと以下のように書けます:

Class.new { include Foo }.new.bar(1)
Seiei
  • 1,968
  • 9
  • 16
4

インスタンスメソッドである事が必要条件なのでしょうか?

その場合、Object.new.extend(Foo)では特異メソッドになってしまいますし、クラスメソッドにしても目的は果たせないと思います。

Object.class_eval { include Foo }.new.bar 1

上記の様にincludeを行えばインスタンスメソッドとしてテストできませんか。

単純にメソッドの入力と出力をテストしたいのであれば、一番実行しやすい構文でいいと思います。

特異クラス・特異メソッド・メソッドの種類 Ruby

eccyan
  • 305
  • 2
  • 10
1

rspec などでモックオブジェクトを利用するという手もあると思います。

cul8er
  • 1,943
  • 3
  • 19
  • 37