2014-12-07 95 views
10

我在SO/Google上找到這個特殊情況的時間很糟糕。我有一個帶有函數的模塊,並且爲了使用它們,您必須創建一個包含/擴展模塊的類,具體取決於您是否需要實例方法或類方法。使用rspec測試Ruby模塊

module A 
    def say_hello name 
    "hello #{name}" 
    end 

    def say_bye 
    "bye" 
    end 
end 

如何使用RSpec的我測試這個模塊?

我有這樣的事情,我不確定我應該在哪裏創建類並擴展Module。

describe A do 
    class MyClass 
    extend A 
    end 

    before(:each) { @name = "Radu" } 

    describe "#say_hello" do 
    it "should greet a name" do 
     expect(Myclass.say_hello(@name)).to eq "hello Radu" 
    end 
    end 
end 

謝謝!

+1

你的方法不返回此值。你應該檢查它是否存在,這樣''puts'方法調用一次參數'hello Radu' – zishe 2014-12-07 10:51:12

+0

@zishe yep'say_hello(@name)'return'nil'。 – 2014-12-07 10:53:35

+1

這是一個愚蠢的例子。我有方法返回的東西。我關心的是如何在rspec中使用擴展 – radubogdan 2014-12-07 11:19:48

回答

24

您可以在測試中創建一個匿名類:

describe A do 
    let(:extended_class) { Class.new { extend A } } 
    let(:including_class) { Class.new { include A } } 

    it "works" do 
    # do stuff with extended_class.say_hello 
    # do stuff with including_class.new.say_hello 
    end 
end 

要看到真正的代碼類似的東西,我用這個策略testing my attr_extras lib

也就是說,includeextend是Ruby的標準特性,所以我不會測試每個模塊在包含和擴展時都能工作 - 通常是給定的。

如果您在測試中創建了一個命名類,就像您在問題中所做的那樣,我相信這個類將在您的測試運行期間全局存在。所以這個類將在你的測試套件的每個測試之間泄漏,可能導致某處的衝突。

如果您使用let來創建一個匿名類,它只會在此特定測試中可用。沒有一個指向它的全球常數可能會與其他測試產生衝突。

+0

我仍然獲得'未定義的方法'my_method'爲#',但也許是我的錯。謝謝你們的快速響應。 – radubogdan 2014-12-07 11:26:16

+0

@radubogdan我嘗試將[精確的代碼(Gist鏈接)](https://gist.github.com/henrik/8d400883a99779de4926)粘貼到現有的RSpec測試中,並且它通過了,所以也許別的東西是錯的? – 2014-12-07 11:29:42

+0

是的,肯定還有別的錯,但我找不到。可能是spec_helper? (我使用rspec --init創建了spec_helper,rspec版本是3.1.7) – radubogdan 2014-12-07 11:49:03

0

助陣未來的讀者,這裏有一個例子使用@亨裏克-N的解決方案,我竟能:

# slim_helpers.rb 
module SlimHelpers 

    # resourceToTitle converts strings like 'AWS::AutoScaling::AutoScalingGroup' 
    # to 'Auto Scaling Group' 
    def resourceToTitle(input) 
    input.split('::')[-1].gsub(/([A-Z])/, ' \1').lstrip 
    end 

end 

# slim_helpers_spec.rb 
require_relative '../slim_helpers' 

describe SlimHelpers do 

    # extended class 
    let(:ec) { Class.new { extend SlimHelpers } } 

    it "converts AWS resource strings to titles" do 
    out = ec.resourceToTitle('AWS::AutoScaling::AutoScalingGroup') 
    expect(out).to eq 'Auto Scaling Group' 
    end 
end 
+0

如果你需要測試類的方法,你也可以使用'Class.extend(SlimHelpers)'。 – czerasz 2016-07-28 11:51:38