require 'assert' require 'assert/stub' class Assert::Stub class UnitTests < Assert::Context desc "Assert::Stub" setup do @myclass = Class.new do def mymeth; 'meth'; end def myval(val); val; end def myargs(*args); args; end def myvalargs(val1, val2, *args); [val1, val2, args]; end def myblk(&block); block.call; end end @myobj = @myclass.new @stub = Assert::Stub.new(@myobj, :mymeth) end subject{ @stub } should have_readers :method_name, :name, :do should have_writers :do should have_cmeths :key should "generate a key given an object and method name" do obj = @myobj meth = :mymeth assert_equal "--#{obj.object_id}--#{meth}--", Assert::Stub.key(obj, meth) end should "know its names" do assert_equal 'mymeth', subject.method_name assert_equal "__assert_stub__#{subject.method_name}", subject.name end should "complain when called if no do block was given" do assert_raises Assert::StubError do @myobj.mymeth end subject.do = proc{ 'mymeth' } assert_nothing_raised do @myobj.mymeth end assert_nothing_raised do Assert::Stub.new(@myobj, :mymeth){ 'mymeth' } end end should "complain if stubbing a method that the object doesn't respond to" do assert_raises Assert::StubError do Assert::Stub.new(@myobj, :some_other_meth) end end should "complain if stubbed and called with no `do` proc given" do assert_raises(Assert::StubError){ @myobj.mymeth } end should "complain if stubbed and called with mismatched arity" do Assert::Stub.new(@myobj, :myval){ 'myval' } assert_raises(Assert::StubError){ @myobj.myval } assert_nothing_raised { @myobj.myval(1) } assert_raises(Assert::StubError){ @myobj.myval(1,2) } Assert::Stub.new(@myobj, :myargs){ 'myargs' } assert_nothing_raised { @myobj.myargs } assert_nothing_raised { @myobj.myargs(1) } assert_nothing_raised { @myobj.myargs(1,2) } Assert::Stub.new(@myobj, :myvalargs){ 'myvalargs' } assert_raises(Assert::StubError){ @myobj.myvalargs } assert_raises(Assert::StubError){ @myobj.myvalargs(1) } assert_nothing_raised { @myobj.myvalargs(1,2) } assert_nothing_raised { @myobj.myvalargs(1,2,3) } end should "complain if stubbed with mismatched arity" do assert_raises(Assert::StubError) do Assert::Stub.new(@myobj, :myval).with(){ 'myval' } end assert_raises(Assert::StubError) do Assert::Stub.new(@myobj, :myval).with(1,2){ 'myval' } end assert_nothing_raised do Assert::Stub.new(@myobj, :myval).with(1){ 'myval' } end assert_nothing_raised do Assert::Stub.new(@myobj, :myargs).with(){ 'myargs' } end assert_nothing_raised do Assert::Stub.new(@myobj, :myargs).with(1,2){ 'myargs' } end assert_nothing_raised do Assert::Stub.new(@myobj, :myargs).with(1){ 'myargs' } end assert_raises(Assert::StubError) do Assert::Stub.new(@myobj, :myvalargs).with(){ 'myvalargs' } end assert_raises(Assert::StubError) do Assert::Stub.new(@myobj, :myvalargs).with(1){ 'myvalargs' } end assert_nothing_raised do Assert::Stub.new(@myobj, :myvalargs).with(1,2){ 'myvalargs' } end assert_nothing_raised do Assert::Stub.new(@myobj, :myvalargs).with(1,2,3){ 'myvalargs' } end end should "stub methods with no args" do subject.teardown assert_equal 'meth', @myobj.mymeth Assert::Stub.new(@myobj, :mymeth){ 'mymeth' } assert_equal 'mymeth', @myobj.mymeth end should "stub methods with required arg" do assert_equal 1, @myobj.myval(1) stub = Assert::Stub.new(@myobj, :myval){ |val| val.to_s } assert_equal '1', @myobj.myval(1) assert_equal '2', @myobj.myval(2) stub.with(2){ 'two' } assert_equal 'two', @myobj.myval(2) end should "stub methods with variable args" do assert_equal [1,2], @myobj.myargs(1,2) stub = Assert::Stub.new(@myobj, :myargs){ |*args| args.join(',') } assert_equal '1,2', @myobj.myargs(1,2) assert_equal '3,4,5', @myobj.myargs(3,4,5) stub.with(3,4,5){ 'three-four-five' } assert_equal 'three-four-five', @myobj.myargs(3,4,5) end should "stub methods with required args and variable args" do assert_equal [1,2, [3]], @myobj.myvalargs(1,2,3) stub = Assert::Stub.new(@myobj, :myvalargs){ |*args| args.join(',') } assert_equal '1,2,3', @myobj.myvalargs(1,2,3) assert_equal '3,4,5', @myobj.myvalargs(3,4,5) stub.with(3,4,5){ 'three-four-five' } assert_equal 'three-four-five', @myobj.myvalargs(3,4,5) end should "stub methods that yield blocks" do blkcalled = false blk = proc{ blkcalled = true } @myobj.myblk(&blk) assert_equal true, blkcalled blkcalled = false Assert::Stub.new(@myobj, :myblk){ blkcalled = 'true' } @myobj.myblk(&blk) assert_equal 'true', blkcalled end should "stub methods even if they are from a super class" do mysubclass = Class.new(@myclass) mysubobj = mysubclass.new assert_equal 1, mysubobj.myval(1) stub = Assert::Stub.new(mysubobj, :myval){ |val| val.to_s } assert_equal '1', mysubobj.myval(1) assert_equal '2', mysubobj.myval(2) stub.with(2){ 'two' } assert_equal 'two', mysubobj.myval(2) end should "be removable" do assert_equal 1, @myobj.myval(1) stub = Assert::Stub.new(@myobj, :myval){ |val| val.to_s } assert_equal '1', @myobj.myval(1) stub.teardown assert_equal 1, @myobj.myval(1) end end class NullStubTests < UnitTests desc "NullStub" setup do @ns = NullStub.new end subject{ @ns } should have_imeths :teardown end end