muack 0.5.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +42 -0
- data/README.md +49 -8
- data/lib/muack.rb +6 -10
- data/lib/muack/any_instance_of.rb +5 -1
- data/lib/muack/definition.rb +2 -1
- data/lib/muack/error.rb +18 -0
- data/lib/muack/mock.rb +40 -18
- data/lib/muack/modifier.rb +12 -1
- data/lib/muack/session.rb +7 -7
- data/lib/muack/spy.rb +23 -0
- data/lib/muack/stub.rb +5 -6
- data/lib/muack/version.rb +1 -1
- data/muack.gemspec +4 -3
- data/test/test_any_instance_of.rb +52 -13
- data/test/test_mock.rb +7 -7
- data/test/test_proxy.rb +28 -16
- data/test/test_satisfy.rb +6 -6
- data/test/test_stub.rb +92 -1
- metadata +4 -3
- data/lib/muack/proxy.rb +0 -39
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: f7727020cca0c41dfd846c0b7628aec71c2cbb59
         | 
| 4 | 
            +
              data.tar.gz: 9fb966eb9e9e1dc65d8f0e938d2d0a619813f204
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 669fbb6e488468cf698bf28782e989f70a7fa82c447b91ef4efdc62892add2bf828d9604d682fbe4b13780cf1599017fbfff22f5d7fa8bbb43c0603b7e5b5d97
         | 
| 7 | 
            +
              data.tar.gz: b6465725ab6109aeead47a3bba111df9095434ec557017ad0141c1ff441e51054504f4217d19fc6b9e1ad2ef2e86e6fdd8cc59cc3568d2498b89bdd30e257dd4
         | 
    
        data/CHANGES.md
    CHANGED
    
    | @@ -1,5 +1,47 @@ | |
| 1 1 | 
             
            # CHANGES
         | 
| 2 2 |  | 
| 3 | 
            +
            ## Muack 0.7.0 -- 2013-06-27
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ### Incompatible changes
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            * Now instead of using mock_proxy, we use `proxy` as a modifier. That says
         | 
| 8 | 
            +
              mock_proxy and stub_proxy no longer existed. like this:
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            ``` ruby
         | 
| 11 | 
            +
            mock(object).to_s.proxy
         | 
| 12 | 
            +
            stub(object).to_s.proxy
         | 
| 13 | 
            +
            ```
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            We change this due to the introduction of spies.
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            ### Enhancement
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            * We have spies support now. Here's an example:
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            ``` ruby
         | 
| 22 | 
            +
            subject = Object.new
         | 
| 23 | 
            +
            stub(subject).foo(1)
         | 
| 24 | 
            +
            subject.foo(1)
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            spy(subject).foo(1)
         | 
| 27 | 
            +
            spy(subject).bar # This doesn't verify immediately.
         | 
| 28 | 
            +
            Muack.verify     # This fails, saying `bar` was never called.
         | 
| 29 | 
            +
            ```
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            * It would now raise a `StubHasNoTimes` exception if you tried to set times
         | 
| 32 | 
            +
              on stubs, which has no meanings in Muack. Use `mock` or `spy` instead if
         | 
| 33 | 
            +
              you need to specify times.
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            * Muack.reset and Muack.verify is now thread-safe.
         | 
| 36 | 
            +
              You can run test cases concurrently now.
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            * AnyInstanceOf now has a more readable inspect.
         | 
| 39 | 
            +
            * Improved various error messages. e.g. CannotFindInjectionName.
         | 
| 40 | 
            +
            * You can now set ENV['MUACK_RECURSION_LEVEL'] to raise the limit
         | 
| 41 | 
            +
              to find a new method name when we're injecting a method. Normally
         | 
| 42 | 
            +
              this should not happen, and it could be a bug in Muack. But instead of
         | 
| 43 | 
            +
              putting a magic number 9 out there as before, this might be better.
         | 
| 44 | 
            +
             | 
| 3 45 | 
             
            ## Muack 0.5.2 -- 2013-06-26
         | 
| 4 46 |  | 
| 5 47 | 
             
            * Add `returns` modifier which you can pass the return values if passing
         | 
    
        data/README.md
    CHANGED
    
    | @@ -101,27 +101,47 @@ User.find('42').times(0) | |
| 101 101 | 
             
            User.find('42') # raises a Muack::Unexpected
         | 
| 102 102 | 
             
            ```
         | 
| 103 103 |  | 
| 104 | 
            -
            #### [ | 
| 104 | 
            +
            #### [proxy](https://github.com/rr/rr/blob/e4b4907fd0488738affb4dab8ce88cbe9fa6580e/doc/03_api_overview.md#mockproxy)
         | 
| 105 105 |  | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 106 | 
            +
            Instead of calling `proxy` immediately after calling `mock`, we put
         | 
| 107 | 
            +
            `proxy` the last because it's a method from `Muack::Modifier`.
         | 
| 108 108 |  | 
| 109 109 | 
             
            ``` ruby
         | 
| 110 110 | 
             
            view = controller.template
         | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 111 | 
            +
            mock(view).render(:partial => "right_navigation").proxy
         | 
| 112 | 
            +
            mock(view).render(:partial => "user_info") do |html|
         | 
| 113 | 
            +
              html.should include("John Doe")
         | 
| 114 | 
            +
              "Different html"
         | 
| 115 | 
            +
            end.proxy
         | 
| 116 | 
            +
            ```
         | 
| 117 | 
            +
             | 
| 118 | 
            +
            If you feel it is weird to put proxy the last, you can also use
         | 
| 119 | 
            +
            `returns` modifier to put the block last as this:
         | 
| 120 | 
            +
             | 
| 121 | 
            +
            ``` ruby
         | 
| 122 | 
            +
            view = controller.template
         | 
| 123 | 
            +
            mock(view).render(:partial => "right_navigation").proxy
         | 
| 124 | 
            +
            mock(view).render(:partial => "user_info").proxy.returns do |html|
         | 
| 113 125 | 
             
              html.should include("John Doe")
         | 
| 114 126 | 
             
              "Different html"
         | 
| 115 127 | 
             
            end
         | 
| 116 128 | 
             
            ```
         | 
| 117 129 |  | 
| 118 | 
            -
             | 
| 130 | 
            +
            The same goes to `stub`.
         | 
| 119 131 |  | 
| 120 | 
            -
             | 
| 132 | 
            +
            ``` ruby
         | 
| 133 | 
            +
            view = controller.template
         | 
| 134 | 
            +
            stub(view).render(:partial => "user_info") do |html|
         | 
| 135 | 
            +
              html.should include("Joe Smith")
         | 
| 136 | 
            +
              html
         | 
| 137 | 
            +
            end.proxy
         | 
| 138 | 
            +
            ```
         | 
| 139 | 
            +
             | 
| 140 | 
            +
            Or use `returns`:
         | 
| 121 141 |  | 
| 122 142 | 
             
            ``` ruby
         | 
| 123 143 | 
             
            view = controller.template
         | 
| 124 | 
            -
             | 
| 144 | 
            +
            stub(view).render(:partial => "user_info").proxy.returns do |html|
         | 
| 125 145 | 
             
              html.should include("Joe Smith")
         | 
| 126 146 | 
             
              html
         | 
| 127 147 | 
             
            end
         | 
| @@ -141,6 +161,27 @@ any_instance_of(User) do |u| | |
| 141 161 | 
             
            end
         | 
| 142 162 | 
             
            ```
         | 
| 143 163 |  | 
| 164 | 
            +
            #### [Spies](https://github.com/rr/rr/blob/e4b4907fd0488738affb4dab8ce88cbe9fa6580e/doc/03_api_overview.md#spies)
         | 
| 165 | 
            +
             | 
| 166 | 
            +
            We don't try to provide different methods for different testing framework,
         | 
| 167 | 
            +
            so that we don't have to create so many testing framework adapters, and
         | 
| 168 | 
            +
            try to be smart to find the correct adapter. There are simply too many
         | 
| 169 | 
            +
            testing frameworks out there. Ruby's built-in test/unit and minitest have
         | 
| 170 | 
            +
            a lot of different versions, so does rspec.
         | 
| 171 | 
            +
             | 
| 172 | 
            +
            Here we just try to do it the Muack's way:
         | 
| 173 | 
            +
             | 
| 174 | 
            +
             | 
| 175 | 
            +
            ``` ruby
         | 
| 176 | 
            +
            subject = Object.new
         | 
| 177 | 
            +
            stub(subject).foo(1)
         | 
| 178 | 
            +
            subject.foo(1)
         | 
| 179 | 
            +
             | 
| 180 | 
            +
            spy(subject).foo(1)
         | 
| 181 | 
            +
            spy(subject).bar # This doesn't verify immediately.
         | 
| 182 | 
            +
            Muack.verify     # This fails, saying `bar` was never called.
         | 
| 183 | 
            +
            ```
         | 
| 184 | 
            +
             | 
| 144 185 | 
             
            #### [Block form](https://github.com/rr/rr/blob/e4b4907fd0488738affb4dab8ce88cbe9fa6580e/doc/03_api_overview.md#block-syntax)
         | 
| 145 186 |  | 
| 146 187 | 
             
            Block form is also supported. However we don't support `instance_eval` form.
         | 
    
        data/lib/muack.rb
    CHANGED
    
    | @@ -10,12 +10,13 @@ module Muack | |
| 10 10 | 
             
              end
         | 
| 11 11 |  | 
| 12 12 | 
             
              def self.session
         | 
| 13 | 
            -
                 | 
| 13 | 
            +
                Thread.current[:muack_session] ||= Muack::Session.new
         | 
| 14 14 | 
             
              end
         | 
| 15 15 |  | 
| 16 16 | 
             
              def self.reset
         | 
| 17 | 
            -
                 | 
| 18 | 
            -
                 | 
| 17 | 
            +
                session = Thread.current[:muack_session]
         | 
| 18 | 
            +
                session && session.reset
         | 
| 19 | 
            +
                Thread.current[:muack_session] = nil
         | 
| 19 20 | 
             
              end
         | 
| 20 21 |  | 
| 21 22 | 
             
              module API
         | 
| @@ -30,13 +31,8 @@ module Muack | |
| 30 31 | 
             
                  if block_given? then yield(ret) else ret end
         | 
| 31 32 | 
             
                end
         | 
| 32 33 |  | 
| 33 | 
            -
                def  | 
| 34 | 
            -
                  ret = Muack.session. | 
| 35 | 
            -
                  if block_given? then yield(ret) else ret end
         | 
| 36 | 
            -
                end
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                def stub_proxy obj=Object.new
         | 
| 39 | 
            -
                  ret = Muack.session.stub_proxy(obj)
         | 
| 34 | 
            +
                def spy obj
         | 
| 35 | 
            +
                  ret = Muack.session.spy(obj)
         | 
| 40 36 | 
             
                  if block_given? then yield(ret) else ret end
         | 
| 41 37 | 
             
                end
         | 
| 42 38 |  | 
    
        data/lib/muack/definition.rb
    CHANGED
    
    
    
        data/lib/muack/error.rb
    ADDED
    
    | @@ -0,0 +1,18 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            module Muack
         | 
| 3 | 
            +
              Error = Class.new(NotImplementedError)
         | 
| 4 | 
            +
              class CannotFindInjectionName < Error
         | 
| 5 | 
            +
                def initialize t, msg
         | 
| 6 | 
            +
                  super "\nCan't find a new method name for :#{msg}, tried #{t} times." \
         | 
| 7 | 
            +
                        "\nSet ENV['MUACK_RECURSION_LEVEL'] to raise this limit."
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              class StubHasNoTimes < Error
         | 
| 12 | 
            +
                def initialize obj, defi, times
         | 
| 13 | 
            +
                  super "\nUse mocks if you want to specify times.\ne.g. "          \
         | 
| 14 | 
            +
                        "mock(#{obj.inspect}).#{defi.msg}(#{defi.args.join(', ')})" \
         | 
| 15 | 
            +
                        ".times(#{times})"
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
    
        data/lib/muack/mock.rb
    CHANGED
    
    | @@ -2,6 +2,7 @@ | |
| 2 2 | 
             
            require 'muack/definition'
         | 
| 3 3 | 
             
            require 'muack/modifier'
         | 
| 4 4 | 
             
            require 'muack/failure'
         | 
| 5 | 
            +
            require 'muack/error'
         | 
| 5 6 |  | 
| 6 7 | 
             
            module Muack
         | 
| 7 8 | 
             
              class Mock < BasicObject
         | 
| @@ -16,7 +17,7 @@ module Muack | |
| 16 17 |  | 
| 17 18 | 
             
                # Public API: Bacon needs this, or we often ended up with stack overflow
         | 
| 18 19 | 
             
                def inspect
         | 
| 19 | 
            -
                  " | 
| 20 | 
            +
                  "Muack::API.#{__mock_class.name[/\w+$/].downcase}(#{object.inspect})"
         | 
| 20 21 | 
             
                end
         | 
| 21 22 |  | 
| 22 23 | 
             
                # Public API: Define mocked method
         | 
| @@ -41,12 +42,17 @@ module Muack | |
| 41 42 | 
             
                  __mock_defis[defi.msg].pop
         | 
| 42 43 | 
             
                end
         | 
| 43 44 |  | 
| 45 | 
            +
                # used for Muack::Modifier#times to determine if it's a mock or not
         | 
| 46 | 
            +
                def __mock_class
         | 
| 47 | 
            +
                  (class << self; self; end).superclass
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 44 50 | 
             
                # used for mocked object to dispatch mocked method
         | 
| 45 | 
            -
                def __mock_dispatch msg, actual_args | 
| 51 | 
            +
                def __mock_dispatch msg, actual_args
         | 
| 46 52 | 
             
                  if defi = __mock_defis[msg].shift
         | 
| 47 53 | 
             
                    __mock_disps_push(defi)
         | 
| 48 54 | 
             
                    if __mock_check_args(defi.args, actual_args)
         | 
| 49 | 
            -
                       | 
| 55 | 
            +
                      defi
         | 
| 50 56 | 
             
                    else
         | 
| 51 57 | 
             
                      Mock.__send__(:raise, # Wrong argument
         | 
| 52 58 | 
             
                        Unexpected.new(object, [defi], msg, actual_args))
         | 
| @@ -63,6 +69,25 @@ module Muack | |
| 63 69 | 
             
                  end
         | 
| 64 70 | 
             
                end
         | 
| 65 71 |  | 
| 72 | 
            +
                # used for mocked object to dispatch mocked method
         | 
| 73 | 
            +
                def __mock_dispatch_call disp, actual_args, actual_block
         | 
| 74 | 
            +
                  if disp.proxy
         | 
| 75 | 
            +
                    value = yield # need the original context for proxy or AnyInstanceOf
         | 
| 76 | 
            +
                    if disp.block
         | 
| 77 | 
            +
                      disp.block.call(value)
         | 
| 78 | 
            +
                    else
         | 
| 79 | 
            +
                      value
         | 
| 80 | 
            +
                    end
         | 
| 81 | 
            +
                  elsif block = disp.block
         | 
| 82 | 
            +
                    arity = block.arity
         | 
| 83 | 
            +
                    if arity < 0
         | 
| 84 | 
            +
                      block.call(*actual_args             , &actual_block)
         | 
| 85 | 
            +
                    else
         | 
| 86 | 
            +
                      block.call(*actual_args.first(arity), &actual_block)
         | 
| 87 | 
            +
                    end
         | 
| 88 | 
            +
                  end
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
             | 
| 66 91 | 
             
                # used for Muack::Session#verify
         | 
| 67 92 | 
             
                def __mock_verify
         | 
| 68 93 | 
             
                  __mock_defis.values.all?(&:empty?) || begin
         | 
| @@ -94,7 +119,7 @@ module Muack | |
| 94 119 | 
             
                private
         | 
| 95 120 | 
             
                def __mock_inject_method defi
         | 
| 96 121 | 
             
                  __mock_injected[defi.msg] = defi
         | 
| 97 | 
            -
                  target = object.singleton_class
         | 
| 122 | 
            +
                  target = object.singleton_class # would be the class in AnyInstanceOf
         | 
| 98 123 | 
             
                  Mock.store_original_method(target, defi)
         | 
| 99 124 | 
             
                   __mock_inject_mock_method(target, defi)
         | 
| 100 125 | 
             
                end
         | 
| @@ -108,8 +133,9 @@ module Muack | |
| 108 133 | 
             
                end
         | 
| 109 134 |  | 
| 110 135 | 
             
                def self.find_new_name klass, message, level=0
         | 
| 111 | 
            -
                   | 
| 112 | 
            -
                    level  | 
| 136 | 
            +
                  if level >= (::ENV['MUACK_RECURSION_LEVEL'] || 9).to_i
         | 
| 137 | 
            +
                    raise CannotFindInjectionName.new(level+1, message)
         | 
| 138 | 
            +
                  end
         | 
| 113 139 |  | 
| 114 140 | 
             
                  new_name = "__muack_mock_#{level}_#{message}".to_sym
         | 
| 115 141 | 
             
                  if klass.instance_methods(false).include?(new_name)
         | 
| @@ -122,21 +148,17 @@ module Muack | |
| 122 148 | 
             
                def __mock_inject_mock_method target, defi
         | 
| 123 149 | 
             
                  mock = self # remember the context
         | 
| 124 150 | 
             
                  target.__send__(:define_method, defi.msg){|*actual_args, &actual_block|
         | 
| 125 | 
            -
                    mock.__mock_dispatch(defi.msg, actual_args | 
| 151 | 
            +
                    disp = mock.__mock_dispatch(defi.msg, actual_args)
         | 
| 152 | 
            +
                    mock.__mock_dispatch_call(disp, actual_args, actual_block){
         | 
| 153 | 
            +
                      if disp.original_method
         | 
| 154 | 
            +
                        __send__(disp.original_method, *actual_args, &actual_block)
         | 
| 155 | 
            +
                      else
         | 
| 156 | 
            +
                        super(*actual_args, &actual_block)
         | 
| 157 | 
            +
                      end
         | 
| 158 | 
            +
                    }
         | 
| 126 159 | 
             
                  }
         | 
| 127 160 | 
             
                end
         | 
| 128 161 |  | 
| 129 | 
            -
                def __mock_block_call defi, actual_args, actual_block
         | 
| 130 | 
            -
                  if block = defi.block
         | 
| 131 | 
            -
                    arity = block.arity
         | 
| 132 | 
            -
                    if arity < 0
         | 
| 133 | 
            -
                      block.call(*actual_args             , &actual_block)
         | 
| 134 | 
            -
                    else
         | 
| 135 | 
            -
                      block.call(*actual_args.first(arity), &actual_block)
         | 
| 136 | 
            -
                    end
         | 
| 137 | 
            -
                  end
         | 
| 138 | 
            -
                end
         | 
| 139 | 
            -
             | 
| 140 162 | 
             
                def __mock_check_args expected_args, actual_args
         | 
| 141 163 | 
             
                  if expected_args == [WithAnyArgs]
         | 
| 142 164 | 
             
                    true
         | 
    
        data/lib/muack/modifier.rb
    CHANGED
    
    | @@ -1,5 +1,5 @@ | |
| 1 1 |  | 
| 2 | 
            -
            require 'muack/ | 
| 2 | 
            +
            require 'muack/error'
         | 
| 3 3 |  | 
| 4 4 | 
             
            module Muack
         | 
| 5 5 | 
             
              class Modifier < Struct.new(:mock, :defi)
         | 
| @@ -12,10 +12,21 @@ module Muack | |
| 12 12 | 
             
                # Public API
         | 
| 13 13 | 
             
                def returns val=nil, &block
         | 
| 14 14 | 
             
                  defi.block = block || lambda{ val }
         | 
| 15 | 
            +
                  self
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                # Public API
         | 
| 19 | 
            +
                def proxy
         | 
| 20 | 
            +
                  defi.proxy = true
         | 
| 21 | 
            +
                  self
         | 
| 15 22 | 
             
                end
         | 
| 16 23 |  | 
| 17 24 | 
             
                # Public API
         | 
| 18 25 | 
             
                def times number
         | 
| 26 | 
            +
                  if mock.__mock_class == Stub
         | 
| 27 | 
            +
                    raise StubHasNoTimes.new(object, defi, number)
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 19 30 | 
             
                  if number >= 1
         | 
| 20 31 | 
             
                    (number - 1).times{ mock.__mock_defis_push(defi) }
         | 
| 21 32 | 
             
                  elsif number == 0
         | 
    
        data/lib/muack/session.rb
    CHANGED
    
    | @@ -1,18 +1,17 @@ | |
| 1 1 |  | 
| 2 2 | 
             
            require 'muack/mock'
         | 
| 3 3 | 
             
            require 'muack/stub'
         | 
| 4 | 
            -
            require 'muack/ | 
| 4 | 
            +
            require 'muack/spy'
         | 
| 5 5 | 
             
            require 'muack/any_instance_of'
         | 
| 6 6 |  | 
| 7 7 | 
             
            module Muack
         | 
| 8 8 | 
             
              class Session < Hash
         | 
| 9 | 
            -
                def mock | 
| 10 | 
            -
                def stub | 
| 11 | 
            -
                def  | 
| 12 | 
            -
                def stub_proxy obj; self["sp #{obj.__id__}"] ||= StubProxy.new(obj); end
         | 
| 9 | 
            +
                def mock obj; self["mk #{obj.__id__}"] ||= Mock.new(obj)      ; end
         | 
| 10 | 
            +
                def stub obj; self["sb #{obj.__id__}"] ||= Stub.new(obj)      ; end
         | 
| 11 | 
            +
                def spy  obj; self["sy #{obj.__id__}"] ||= Spy .new(stub(obj)); end
         | 
| 13 12 |  | 
| 14 | 
            -
                def any_instance_of  | 
| 15 | 
            -
                  (@ | 
| 13 | 
            +
                def any_instance_of kls
         | 
| 14 | 
            +
                  (@others ||= {})["ai #{kls.__id__}"] ||= AnyInstanceOf.new(kls)
         | 
| 16 15 | 
             
                end
         | 
| 17 16 |  | 
| 18 17 | 
             
                def verify
         | 
| @@ -20,6 +19,7 @@ module Muack | |
| 20 19 | 
             
                end
         | 
| 21 20 |  | 
| 22 21 | 
             
                def reset
         | 
| 22 | 
            +
                  instance_variable_defined?(:@others) && @others.clear
         | 
| 23 23 | 
             
                  each_value(&:__mock_reset)
         | 
| 24 24 | 
             
                  clear
         | 
| 25 25 | 
             
                end
         | 
    
        data/lib/muack/spy.rb
    ADDED
    
    | @@ -0,0 +1,23 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            require 'muack/mock'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module Muack
         | 
| 5 | 
            +
              class Spy < Mock
         | 
| 6 | 
            +
                def initialize stub
         | 
| 7 | 
            +
                  super(stub.object)
         | 
| 8 | 
            +
                  @secret = stub.__mock_disps.values.flatten # steal disps
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                # used for Muack::Session#verify
         | 
| 12 | 
            +
                def __mock_verify
         | 
| 13 | 
            +
                  @secret.each{ |defi| __mock_dispatch(defi.msg, defi.args) }
         | 
| 14 | 
            +
                  super # simulate dispatching before passing to mock to verify
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                # used for Muack::Session#reset, but spies never leave any track
         | 
| 18 | 
            +
                def __mock_reset; end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                private
         | 
| 21 | 
            +
                def __mock_inject_method defi; end # spies don't leave any track
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
    
        data/lib/muack/stub.rb
    CHANGED
    
    | @@ -7,12 +7,11 @@ module Muack | |
| 7 7 | 
             
                def __mock_verify; true; end
         | 
| 8 8 |  | 
| 9 9 | 
             
                # used for mocked object to dispatch mocked method
         | 
| 10 | 
            -
                def __mock_dispatch msg, actual_args | 
| 11 | 
            -
                  defi = __mock_defis[msg].find{ |d|
         | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
                    __mock_block_call(defi, actual_args, actual_block)
         | 
| 10 | 
            +
                def __mock_dispatch msg, actual_args
         | 
| 11 | 
            +
                  if defi = __mock_defis[msg].find{ |d|
         | 
| 12 | 
            +
                              __mock_check_args(d.args, actual_args) }
         | 
| 13 | 
            +
                    __mock_disps_push(defi) # our spies are interested in this
         | 
| 14 | 
            +
                    defi
         | 
| 16 15 | 
             
                  else
         | 
| 17 16 | 
             
                    Mock.__send__(:raise, # Wrong argument
         | 
| 18 17 | 
             
                      Unexpected.new(object, __mock_defis[msg], msg, actual_args))
         | 
    
        data/lib/muack/version.rb
    CHANGED
    
    
    
        data/muack.gemspec
    CHANGED
    
    | @@ -2,11 +2,11 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            Gem::Specification.new do |s|
         | 
| 4 4 | 
             
              s.name = "muack"
         | 
| 5 | 
            -
              s.version = "0. | 
| 5 | 
            +
              s.version = "0.7.0"
         | 
| 6 6 |  | 
| 7 7 | 
             
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         | 
| 8 8 | 
             
              s.authors = ["Lin Jen-Shin (godfat)"]
         | 
| 9 | 
            -
              s.date = "2013-06- | 
| 9 | 
            +
              s.date = "2013-06-27"
         | 
| 10 10 | 
             
              s.description = "Muack -- Yet another mocking library.\n\nBasically it's an [RR][] clone, but much faster under heavy use.\nIt's 32x times faster (750s vs 23s) for running [Rib][] tests.\n\n[RR]: https://github.com/rr/rr\n[Rib]: https://github.com/godfat/rib"
         | 
| 11 11 | 
             
              s.email = ["godfat (XD) godfat.org"]
         | 
| 12 12 | 
             
              s.files = [
         | 
| @@ -21,12 +21,13 @@ Gem::Specification.new do |s| | |
| 21 21 | 
             
              "lib/muack.rb",
         | 
| 22 22 | 
             
              "lib/muack/any_instance_of.rb",
         | 
| 23 23 | 
             
              "lib/muack/definition.rb",
         | 
| 24 | 
            +
              "lib/muack/error.rb",
         | 
| 24 25 | 
             
              "lib/muack/failure.rb",
         | 
| 25 26 | 
             
              "lib/muack/mock.rb",
         | 
| 26 27 | 
             
              "lib/muack/modifier.rb",
         | 
| 27 | 
            -
              "lib/muack/proxy.rb",
         | 
| 28 28 | 
             
              "lib/muack/satisfy.rb",
         | 
| 29 29 | 
             
              "lib/muack/session.rb",
         | 
| 30 | 
            +
              "lib/muack/spy.rb",
         | 
| 30 31 | 
             
              "lib/muack/stub.rb",
         | 
| 31 32 | 
             
              "lib/muack/test.rb",
         | 
| 32 33 | 
             
              "lib/muack/version.rb",
         | 
| @@ -2,8 +2,9 @@ | |
| 2 2 | 
             
            require 'muack/test'
         | 
| 3 3 |  | 
| 4 4 | 
             
            describe Muack::AnyInstanceOf do
         | 
| 5 | 
            +
              klass = Class.new{ def f; 0; end }
         | 
| 6 | 
            +
             | 
| 5 7 | 
             
              should 'mock any_instance_of' do
         | 
| 6 | 
            -
                klass = Class.new
         | 
| 7 8 | 
             
                any_instance_of(klass){ |instance| mock(instance).say{ true } }
         | 
| 8 9 | 
             
                obj = klass.new
         | 
| 9 10 | 
             
                obj.say              .should.eq true
         | 
| @@ -13,17 +14,15 @@ describe Muack::AnyInstanceOf do | |
| 13 14 | 
             
              end
         | 
| 14 15 |  | 
| 15 16 | 
             
              should 'proxy any_instance_of' do
         | 
| 16 | 
            -
                klass  | 
| 17 | 
            -
                any_instance_of(klass){ |instance| mock_proxy(instance).f }
         | 
| 17 | 
            +
                any_instance_of(klass){ |instance| mock(instance).f.proxy }
         | 
| 18 18 | 
             
                obj = klass.new
         | 
| 19 | 
            -
                obj.f       .should.eq  | 
| 19 | 
            +
                obj.f       .should.eq 0
         | 
| 20 20 | 
             
                Muack.verify.should.eq true
         | 
| 21 | 
            -
                obj.f       .should.eq  | 
| 21 | 
            +
                obj.f       .should.eq 0
         | 
| 22 22 | 
             
              end
         | 
| 23 23 |  | 
| 24 24 | 
             
              should 'proxy any_instance_of with a block' do
         | 
| 25 | 
            -
                klass  | 
| 26 | 
            -
                any_instance_of(klass){ |instance| mock_proxy(instance).f{ |i| i+1 } }
         | 
| 25 | 
            +
                any_instance_of(klass){ |instance| mock(instance).f{ |i| i+1 }.proxy }
         | 
| 27 26 | 
             
                obj = klass.new
         | 
| 28 27 | 
             
                obj.f       .should.eq 1
         | 
| 29 28 | 
             
                Muack.verify.should.eq true
         | 
| @@ -31,9 +30,8 @@ describe Muack::AnyInstanceOf do | |
| 31 30 | 
             
              end
         | 
| 32 31 |  | 
| 33 32 | 
             
              should 'proxy with multiple any_instance_of call' do
         | 
| 34 | 
            -
                klass  | 
| 35 | 
            -
                any_instance_of(klass){ |instance|  | 
| 36 | 
            -
                any_instance_of(klass){ |instance| mock_proxy(instance).f{ |i| i+2 } }
         | 
| 33 | 
            +
                any_instance_of(klass){ |instance| mock(instance).f{ |i| i+1 }.proxy }
         | 
| 34 | 
            +
                any_instance_of(klass){ |instance| mock(instance).f{ |i| i+2 }.proxy }
         | 
| 37 35 | 
             
                obj = klass.new
         | 
| 38 36 | 
             
                obj.f.should.eq 1
         | 
| 39 37 | 
             
                obj.f.should.eq 2
         | 
| @@ -42,13 +40,54 @@ describe Muack::AnyInstanceOf do | |
| 42 40 | 
             
              end
         | 
| 43 41 |  | 
| 44 42 | 
             
              should 'mock with multiple any_instance_of call' do
         | 
| 45 | 
            -
                klass = Class.new{ def f; 0; end }
         | 
| 46 43 | 
             
                any_instance_of(klass){ |inst| mock(inst).f(is_a(Fixnum)){ |i| i+1 } }
         | 
| 47 44 | 
             
                any_instance_of(klass){ |inst| mock(inst).f(is_a(Fixnum)){ |i| i+2 } }
         | 
| 48 45 | 
             
                obj = klass.new
         | 
| 49 | 
            -
                obj.f( | 
| 50 | 
            -
                obj.f( | 
| 46 | 
            +
                obj.f(2).should.eq 3
         | 
| 47 | 
            +
                obj.f(2).should.eq 4
         | 
| 48 | 
            +
                Muack.verify.should.eq true
         | 
| 49 | 
            +
                obj.f.should.eq 0
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
              should 'stub proxy with any_instance_of and spy' do
         | 
| 53 | 
            +
                any_instance_of(klass){ |inst| stub(inst).f{ |i| i+3 }.proxy }
         | 
| 54 | 
            +
                obj = klass.new
         | 
| 55 | 
            +
                obj.f.should.eq 3
         | 
| 56 | 
            +
                obj.f.should.eq 3
         | 
| 57 | 
            +
                spy(any_instance_of(klass)).f.times(2)
         | 
| 51 58 | 
             
                Muack.verify.should.eq true
         | 
| 52 59 | 
             
                obj.f.should.eq 0
         | 
| 53 60 | 
             
              end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
              should 'stub with any_instance_of and spy under satisfied' do
         | 
| 63 | 
            +
                any_instance_of(klass){ |inst| stub(inst).f{ 5 } }
         | 
| 64 | 
            +
                obj = klass.new
         | 
| 65 | 
            +
                obj.f.should.eq 5
         | 
| 66 | 
            +
                spy(any_instance_of(klass)).f.times(2)
         | 
| 67 | 
            +
                begin
         | 
| 68 | 
            +
                  Muack.verify
         | 
| 69 | 
            +
                rescue Muack::Expected => e
         | 
| 70 | 
            +
                  expected = /Muack::API\.any_instance_of\(.+?\)\.f\(\)/
         | 
| 71 | 
            +
                  e.expected      .should =~ expected
         | 
| 72 | 
            +
                  e.expected_times.should.eq 2
         | 
| 73 | 
            +
                  e.actual_times  .should.eq 1
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
                obj.f.should.eq 0
         | 
| 76 | 
            +
              end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
              should 'stub with any_instance_of and spy over satisfied' do
         | 
| 79 | 
            +
                any_instance_of(klass){ |inst| stub(inst).f{ 2 } }
         | 
| 80 | 
            +
                obj = klass.new
         | 
| 81 | 
            +
                2.times{ obj.f.should.eq 2 }
         | 
| 82 | 
            +
                spy(any_instance_of(klass)).f
         | 
| 83 | 
            +
                begin
         | 
| 84 | 
            +
                  Muack.verify
         | 
| 85 | 
            +
                rescue Muack::Expected => e
         | 
| 86 | 
            +
                  expected = /Muack::API\.any_instance_of\(.+?\)\.f\(\)/
         | 
| 87 | 
            +
                  e.expected      .should =~ expected
         | 
| 88 | 
            +
                  e.expected_times.should.eq 1
         | 
| 89 | 
            +
                  e.actual_times  .should.eq 2
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
                obj.f.should.eq 0
         | 
| 92 | 
            +
              end
         | 
| 54 93 | 
             
            end
         | 
    
        data/test/test_mock.rb
    CHANGED
    
    | @@ -8,6 +8,10 @@ describe Muack::Mock do | |
| 8 8 | 
             
                  Muack::EnsureReset.call
         | 
| 9 9 | 
             
                end
         | 
| 10 10 |  | 
| 11 | 
            +
                should 'inspect' do
         | 
| 12 | 
            +
                  mock(Obj).inspect.should.eq "Muack::API.mock(obj)"
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 11 15 | 
             
                should 'mock with regular method' do
         | 
| 12 16 | 
             
                  mock(Obj).say(true){ 'boo' }
         | 
| 13 17 | 
             
                  Obj.say(true).should.eq 'boo'
         | 
| @@ -58,10 +62,6 @@ describe Muack::Mock do | |
| 58 62 | 
             
                  mock.say{1}.object.say.should.eq 1
         | 
| 59 63 | 
             
                end
         | 
| 60 64 |  | 
| 61 | 
            -
                should 'inspect' do
         | 
| 62 | 
            -
                  mock(Obj).inspect.should.eq "#<Muack::Mock object=obj>"
         | 
| 63 | 
            -
                end
         | 
| 64 | 
            -
             | 
| 65 65 | 
             
                should 'mock and call, mock and call' do
         | 
| 66 66 | 
             
                  mock(Obj).say{0}
         | 
| 67 67 | 
             
                  Obj.say.should.eq 0
         | 
| @@ -94,7 +94,7 @@ describe Muack::Mock do | |
| 94 94 | 
             
                  Muack::EnsureReset.call
         | 
| 95 95 | 
             
                end
         | 
| 96 96 |  | 
| 97 | 
            -
                should 'raise  | 
| 97 | 
            +
                should 'raise Unexpected error if passing unexpected argument' do
         | 
| 98 98 | 
             
                  mock(Obj).say(true){ 'boo' }
         | 
| 99 99 | 
             
                  begin
         | 
| 100 100 | 
             
                    Obj.say(false)
         | 
| @@ -144,7 +144,7 @@ describe Muack::Mock do | |
| 144 144 | 
             
                  end
         | 
| 145 145 | 
             
                end
         | 
| 146 146 |  | 
| 147 | 
            -
                should 'raise  | 
| 147 | 
            +
                should 'raise Unexpected when calling with diff sig' do
         | 
| 148 148 | 
             
                  mock(Obj).say(true){1}
         | 
| 149 149 | 
             
                  Obj.say(true).should.eq 1
         | 
| 150 150 | 
             
                  begin
         | 
| @@ -157,7 +157,7 @@ describe Muack::Mock do | |
| 157 157 | 
             
                  end
         | 
| 158 158 | 
             
                end
         | 
| 159 159 |  | 
| 160 | 
            -
                should 'raise  | 
| 160 | 
            +
                should 'raise Expected error if mock methods not called' do
         | 
| 161 161 | 
             
                  mock(Obj).say(true){ 'boo' }
         | 
| 162 162 | 
             
                  begin
         | 
| 163 163 | 
             
                    Muack.verify
         | 
    
        data/test/test_proxy.rb
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 |  | 
| 2 2 | 
             
            require 'muack/test'
         | 
| 3 3 |  | 
| 4 | 
            -
            describe Muack:: | 
| 4 | 
            +
            describe Muack::Mock do
         | 
| 5 5 | 
             
              describe 'Muack.verify==true' do
         | 
| 6 6 | 
             
                after do
         | 
| 7 7 | 
             
                  Muack.verify.should.eq true
         | 
| @@ -9,48 +9,60 @@ describe Muack::Proxy do | |
| 9 9 | 
             
                end
         | 
| 10 10 |  | 
| 11 11 | 
             
                should 'proxy with regular method' do
         | 
| 12 | 
            -
                   | 
| 12 | 
            +
                  mock(Str).reverse.proxy
         | 
| 13 13 | 
             
                  Str.reverse.should.eq 'ooM'
         | 
| 14 14 | 
             
                end
         | 
| 15 15 |  | 
| 16 16 | 
             
                should 'proxy multiple times' do
         | 
| 17 | 
            -
                  2.times{  | 
| 17 | 
            +
                  2.times{ mock(Str).reverse.proxy }
         | 
| 18 18 | 
             
                  2.times{ Str.reverse.should.eq 'ooM' }
         | 
| 19 19 | 
             
                end
         | 
| 20 20 |  | 
| 21 21 | 
             
                should 'proxy multiple times with super method' do
         | 
| 22 | 
            -
                  2.times{  | 
| 22 | 
            +
                  2.times{ mock(Str).class.proxy }
         | 
| 23 23 | 
             
                  2.times{ Str.class.should.eq String }
         | 
| 24 24 | 
             
                end
         | 
| 25 25 |  | 
| 26 | 
            +
                should 'return modifier itself for any modifier methods' do
         | 
| 27 | 
            +
                  mock(Str).to_s.proxy.returns{ |s| s.reverse }.times(2).
         | 
| 28 | 
            +
                    with_any_args.with_any_args
         | 
| 29 | 
            +
                  2.times{ Str.to_s.should.eq 'ooM' }
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 26 32 | 
             
                should 'proxy and call the block' do
         | 
| 27 | 
            -
                   | 
| 33 | 
            +
                  mock(Obj).method_missing(:inspect){ |str| str.reverse }.proxy
         | 
| 28 34 | 
             
                  Obj.inspect.should.eq 'jbo'
         | 
| 29 35 | 
             
                end
         | 
| 30 36 |  | 
| 31 37 | 
             
                should 'proxy and call the block with super' do
         | 
| 32 | 
            -
                   | 
| 38 | 
            +
                  mock(Str).class{ |k| k.name.reverse }.proxy
         | 
| 33 39 | 
             
                  Str.class.should.eq 'gnirtS'
         | 
| 34 40 | 
             
                end
         | 
| 35 41 |  | 
| 36 | 
            -
                should ' | 
| 37 | 
            -
                   | 
| 42 | 
            +
                should 'mock proxy and call, mock proxy and call' do
         | 
| 43 | 
            +
                  mock(Obj).class{ |k| k.name.reverse }.proxy
         | 
| 38 44 | 
             
                  Obj.class.should.eq 'tcejbO'
         | 
| 39 | 
            -
                   | 
| 45 | 
            +
                  mock(Obj).class{ |k| k.name.upcase }.proxy
         | 
| 40 46 | 
             
                  Obj.class.should.eq 'OBJECT'
         | 
| 41 47 | 
             
                end
         | 
| 42 48 |  | 
| 43 | 
            -
                should ' | 
| 44 | 
            -
                   | 
| 49 | 
            +
                should 'stub proxy and call, stub proxy and call' do
         | 
| 50 | 
            +
                  stub(Obj).kind_of?(Object){ |b| !b }.proxy
         | 
| 45 51 | 
             
                  Obj.kind_of?(Object).should.eq false
         | 
| 46 | 
            -
                   | 
| 52 | 
            +
                  stub(Obj).kind_of?(String){ |b| b.to_s }.proxy
         | 
| 47 53 | 
             
                  Obj.kind_of?(String).should.eq 'false'
         | 
| 48 54 | 
             
                end
         | 
| 49 55 |  | 
| 50 | 
            -
                should ' | 
| 51 | 
            -
                   | 
| 56 | 
            +
                should 'stub proxy with any times' do
         | 
| 57 | 
            +
                  stub(Obj).class{ |k| k.name.downcase }.proxy
         | 
| 52 58 | 
             
                  3.times{ Obj.class.should.eq 'object' }
         | 
| 53 59 | 
             
                end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                should 'stub proxy and spy' do
         | 
| 62 | 
            +
                  stub(Obj).class{ |k| k.name.downcase }.proxy
         | 
| 63 | 
            +
                  Obj.class.should.eq 'object'
         | 
| 64 | 
            +
                  spy(Obj).class
         | 
| 65 | 
            +
                end
         | 
| 54 66 | 
             
              end
         | 
| 55 67 |  | 
| 56 68 | 
             
              describe 'Muack.verify==false' do
         | 
| @@ -59,8 +71,8 @@ describe Muack::Proxy do | |
| 59 71 | 
             
                  Muack::EnsureReset.call
         | 
| 60 72 | 
             
                end
         | 
| 61 73 |  | 
| 62 | 
            -
                should 'raise  | 
| 63 | 
            -
                   | 
| 74 | 
            +
                should 'raise Expected error if passing unexpected argument' do
         | 
| 75 | 
            +
                  mock(Str).reverse.proxy
         | 
| 64 76 | 
             
                  Str.reverse.should.eq 'ooM'
         | 
| 65 77 | 
             
                  begin
         | 
| 66 78 | 
             
                    Str.reverse
         | 
    
        data/test/test_satisfy.rb
    CHANGED
    
    | @@ -17,7 +17,7 @@ describe Muack::Satisfy do | |
| 17 17 | 
             
                  Muack::EnsureReset.call
         | 
| 18 18 | 
             
                end
         | 
| 19 19 |  | 
| 20 | 
            -
                should 'raise  | 
| 20 | 
            +
                should 'raise Unexpected error if passing unexpected argument' do
         | 
| 21 21 | 
             
                  mock(Obj).say(is_a(Array)){ 'boo' }
         | 
| 22 22 | 
             
                  begin
         | 
| 23 23 | 
             
                    Obj.say(false)
         | 
| @@ -53,7 +53,7 @@ describe Muack::Satisfy do | |
| 53 53 | 
             
                  Muack::EnsureReset.call
         | 
| 54 54 | 
             
                end
         | 
| 55 55 |  | 
| 56 | 
            -
                should 'raise  | 
| 56 | 
            +
                should 'raise Unexpected error if passing unexpected argument' do
         | 
| 57 57 | 
             
                  mock(Obj).say(anything){ 'boo' }
         | 
| 58 58 | 
             
                  begin
         | 
| 59 59 | 
             
                    Obj.say(6, 7)
         | 
| @@ -84,7 +84,7 @@ describe Muack::Satisfy do | |
| 84 84 | 
             
                  Muack::EnsureReset.call
         | 
| 85 85 | 
             
                end
         | 
| 86 86 |  | 
| 87 | 
            -
                should 'raise  | 
| 87 | 
            +
                should 'raise Unexpected error if passing unexpected argument' do
         | 
| 88 88 | 
             
                  mock(Obj).say(match(/\w/)){ 'boo' }
         | 
| 89 89 | 
             
                  begin
         | 
| 90 90 | 
             
                    Obj.say('!')
         | 
| @@ -115,7 +115,7 @@ describe Muack::Satisfy do | |
| 115 115 | 
             
                  Muack::EnsureReset.call
         | 
| 116 116 | 
             
                end
         | 
| 117 117 |  | 
| 118 | 
            -
                should 'raise  | 
| 118 | 
            +
                should 'raise Unexpected error if passing unexpected argument' do
         | 
| 119 119 | 
             
                  mock(Obj).say(hash_including(:b => 2)){ 'boo' }
         | 
| 120 120 | 
             
                  begin
         | 
| 121 121 | 
             
                    Obj.say(:a => 1)
         | 
| @@ -151,7 +151,7 @@ describe Muack::Satisfy do | |
| 151 151 | 
             
                  Muack::EnsureReset.call
         | 
| 152 152 | 
             
                end
         | 
| 153 153 |  | 
| 154 | 
            -
                should 'raise  | 
| 154 | 
            +
                should 'raise Unexpected error if passing unexpected argument' do
         | 
| 155 155 | 
             
                  mock(Obj).say(within(0..5)){ 'boo' }
         | 
| 156 156 | 
             
                  begin
         | 
| 157 157 | 
             
                    Obj.say(6)
         | 
| @@ -182,7 +182,7 @@ describe Muack::Satisfy do | |
| 182 182 | 
             
                  Muack::EnsureReset.call
         | 
| 183 183 | 
             
                end
         | 
| 184 184 |  | 
| 185 | 
            -
                should 'raise  | 
| 185 | 
            +
                should 'raise Unexpected error if passing unexpected argument' do
         | 
| 186 186 | 
             
                  mock(Obj).say(satisfy{ |arg| arg % 2 == 0 }){ 'boo' }
         | 
| 187 187 | 
             
                  begin
         | 
| 188 188 | 
             
                    Obj.say(1)
         | 
    
        data/test/test_stub.rb
    CHANGED
    
    | @@ -2,12 +2,24 @@ | |
| 2 2 | 
             
            require 'muack/test'
         | 
| 3 3 |  | 
| 4 4 | 
             
            describe Muack::Stub do
         | 
| 5 | 
            +
              should 'raise StubHasNoTimes with stub(obj).f.times(0)' do
         | 
| 6 | 
            +
                lambda{ stub(Obj).f.times(0) }.should.raise(Muack::StubHasNoTimes)
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 5 9 | 
             
              describe 'Muack.verify==true' do
         | 
| 6 10 | 
             
                after do
         | 
| 7 11 | 
             
                  Muack.verify.should.eq true
         | 
| 8 12 | 
             
                  Muack::EnsureReset.call
         | 
| 9 13 | 
             
                end
         | 
| 10 14 |  | 
| 15 | 
            +
                should 'inspect' do
         | 
| 16 | 
            +
                  stub(Obj).inspect.should.eq "Muack::API.stub(obj)"
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                should 'inspect' do
         | 
| 20 | 
            +
                  spy( Obj).inspect.should.eq "Muack::API.spy(obj)"
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 11 23 | 
             
                should 'stub with regular method' do
         | 
| 12 24 | 
             
                  stub(Obj).say{ 'goo' }
         | 
| 13 25 | 
             
                  3.times{ Obj.say.should.eq 'goo' }
         | 
| @@ -26,6 +38,24 @@ describe Muack::Stub do | |
| 26 38 | 
             
                  Obj.saya.should.eq 1
         | 
| 27 39 | 
             
                  Obj.say .should.eq 0
         | 
| 28 40 | 
             
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                should 'work with spy' do
         | 
| 43 | 
            +
                  stub(Obj).say{0}
         | 
| 44 | 
            +
                  Obj.say.should.eq 0
         | 
| 45 | 
            +
                  spy(Obj).say
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                should 'work with spy twice' do
         | 
| 49 | 
            +
                  stub(Obj).say
         | 
| 50 | 
            +
                  2.times{ Obj.say.should.eq nil }
         | 
| 51 | 
            +
                  spy(Obj).say.times(2)
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                should 'work with spy spy' do
         | 
| 55 | 
            +
                  stub(Obj).say
         | 
| 56 | 
            +
                  2.times{ Obj.say.should.eq nil }
         | 
| 57 | 
            +
                  2.times{ spy(Obj).say }
         | 
| 58 | 
            +
                end
         | 
| 29 59 | 
             
              end
         | 
| 30 60 |  | 
| 31 61 | 
             
              describe 'Muack.verify==false' do
         | 
| @@ -34,7 +64,7 @@ describe Muack::Stub do | |
| 34 64 | 
             
                  Muack::EnsureReset.call
         | 
| 35 65 | 
             
                end
         | 
| 36 66 |  | 
| 37 | 
            -
                should 'raise  | 
| 67 | 
            +
                should 'raise Unexpected error if passing unexpected argument' do
         | 
| 38 68 | 
             
                  stub(Obj).say(true){ 'boo' }
         | 
| 39 69 | 
             
                  begin
         | 
| 40 70 | 
             
                    Obj.say(false)
         | 
| @@ -58,5 +88,66 @@ describe Muack::Stub do | |
| 58 88 | 
             
                    e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
         | 
| 59 89 | 
             
                  end
         | 
| 60 90 | 
             
                end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                should 'raise Expected if the spy is not satisfied' do
         | 
| 93 | 
            +
                  stub(Obj).say
         | 
| 94 | 
            +
                  spy( Obj).say
         | 
| 95 | 
            +
                  begin
         | 
| 96 | 
            +
                    Muack.verify
         | 
| 97 | 
            +
                    'never'.should.eq 'reach'
         | 
| 98 | 
            +
                  rescue Muack::Expected => e
         | 
| 99 | 
            +
                    e.expected      .should.eq 'obj.say()'
         | 
| 100 | 
            +
                    e.expected_times.should.eq 1
         | 
| 101 | 
            +
                    e.actual_times  .should.eq 0
         | 
| 102 | 
            +
                    e.message       .should.eq "\nExpected: obj.say()\n  " \
         | 
| 103 | 
            +
                                               "called 1 times\n but was 0 times."
         | 
| 104 | 
            +
                  end
         | 
| 105 | 
            +
                end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                should 'raise Expected if the spy is not satisfied enough' do
         | 
| 108 | 
            +
                  stub(Obj).say
         | 
| 109 | 
            +
                  Obj.say
         | 
| 110 | 
            +
                  spy( Obj).say(0)
         | 
| 111 | 
            +
                  begin
         | 
| 112 | 
            +
                    Muack.verify
         | 
| 113 | 
            +
                    'never'.should.eq 'reach'
         | 
| 114 | 
            +
                  rescue Muack::Unexpected => e
         | 
| 115 | 
            +
                    e.expected.should.eq "obj.say(0)"
         | 
| 116 | 
            +
                    e.was     .should.eq 'obj.say()'
         | 
| 117 | 
            +
                    e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
         | 
| 118 | 
            +
                  end
         | 
| 119 | 
            +
                end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                should 'show correct times for under satisfaction' do
         | 
| 122 | 
            +
                  stub(Obj).say
         | 
| 123 | 
            +
                  2.times{ Obj.say }
         | 
| 124 | 
            +
                  spy( Obj).say.times(3)
         | 
| 125 | 
            +
                  begin
         | 
| 126 | 
            +
                    Muack.verify
         | 
| 127 | 
            +
                    'never'.should.eq 'reach'
         | 
| 128 | 
            +
                  rescue Muack::Expected => e
         | 
| 129 | 
            +
                    e.expected      .should.eq 'obj.say()'
         | 
| 130 | 
            +
                    e.expected_times.should.eq 3
         | 
| 131 | 
            +
                    e.actual_times  .should.eq 2
         | 
| 132 | 
            +
                    e.message       .should.eq "\nExpected: obj.say()\n  " \
         | 
| 133 | 
            +
                                               "called 3 times\n but was 2 times."
         | 
| 134 | 
            +
                  end
         | 
| 135 | 
            +
                end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                should 'show correct times for over satisfaction' do
         | 
| 138 | 
            +
                  stub(Obj).say
         | 
| 139 | 
            +
                  2.times{ Obj.say }
         | 
| 140 | 
            +
                  spy( Obj).say
         | 
| 141 | 
            +
                  begin
         | 
| 142 | 
            +
                    Muack.verify
         | 
| 143 | 
            +
                    'never'.should.eq 'reach'
         | 
| 144 | 
            +
                  rescue Muack::Expected => e
         | 
| 145 | 
            +
                    e.expected      .should.eq 'obj.say()'
         | 
| 146 | 
            +
                    e.expected_times.should.eq 1
         | 
| 147 | 
            +
                    e.actual_times  .should.eq 2
         | 
| 148 | 
            +
                    e.message       .should.eq "\nExpected: obj.say()\n  " \
         | 
| 149 | 
            +
                                               "called 1 times\n but was 2 times."
         | 
| 150 | 
            +
                  end
         | 
| 151 | 
            +
                end
         | 
| 61 152 | 
             
              end
         | 
| 62 153 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: muack
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.7.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Lin Jen-Shin (godfat)
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2013-06- | 
| 11 | 
            +
            date: 2013-06-27 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies: []
         | 
| 13 13 | 
             
            description: |-
         | 
| 14 14 | 
             
              Muack -- Yet another mocking library.
         | 
| @@ -35,12 +35,13 @@ files: | |
| 35 35 | 
             
            - lib/muack.rb
         | 
| 36 36 | 
             
            - lib/muack/any_instance_of.rb
         | 
| 37 37 | 
             
            - lib/muack/definition.rb
         | 
| 38 | 
            +
            - lib/muack/error.rb
         | 
| 38 39 | 
             
            - lib/muack/failure.rb
         | 
| 39 40 | 
             
            - lib/muack/mock.rb
         | 
| 40 41 | 
             
            - lib/muack/modifier.rb
         | 
| 41 | 
            -
            - lib/muack/proxy.rb
         | 
| 42 42 | 
             
            - lib/muack/satisfy.rb
         | 
| 43 43 | 
             
            - lib/muack/session.rb
         | 
| 44 | 
            +
            - lib/muack/spy.rb
         | 
| 44 45 | 
             
            - lib/muack/stub.rb
         | 
| 45 46 | 
             
            - lib/muack/test.rb
         | 
| 46 47 | 
             
            - lib/muack/version.rb
         | 
    
        data/lib/muack/proxy.rb
    DELETED
    
    | @@ -1,39 +0,0 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
            require 'muack/mock'
         | 
| 3 | 
            -
            require 'muack/stub'
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            module Muack
         | 
| 6 | 
            -
              module Proxy
         | 
| 7 | 
            -
                def __mock_block_call defi, actual_args, actual_block
         | 
| 8 | 
            -
                  # handle block call in injected method, since we need to call origin
         | 
| 9 | 
            -
                  defi # but we still want to know which defi gets dispatched!
         | 
| 10 | 
            -
                end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                def __mock_inject_mock_method target, defi
         | 
| 13 | 
            -
                  mock = self # remember the context
         | 
| 14 | 
            -
                  target.__send__(:define_method, defi.msg){|*actual_args, &actual_block|
         | 
| 15 | 
            -
                    d = mock.__mock_dispatch(defi.msg, actual_args, actual_block)
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                    ret = if d.original_method
         | 
| 18 | 
            -
                            __send__(d.original_method, *actual_args, &actual_block)
         | 
| 19 | 
            -
                          else
         | 
| 20 | 
            -
                            super(*actual_args, &actual_block)
         | 
| 21 | 
            -
                          end
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                    if d.block
         | 
| 24 | 
            -
                      d.block.call(ret)
         | 
| 25 | 
            -
                    else
         | 
| 26 | 
            -
                      ret
         | 
| 27 | 
            -
                    end
         | 
| 28 | 
            -
                  }
         | 
| 29 | 
            -
                end
         | 
| 30 | 
            -
              end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
              class MockProxy < Mock
         | 
| 33 | 
            -
                include Proxy
         | 
| 34 | 
            -
              end
         | 
| 35 | 
            -
             | 
| 36 | 
            -
              class StubProxy < Stub
         | 
| 37 | 
            -
                include Proxy
         | 
| 38 | 
            -
              end
         | 
| 39 | 
            -
            end
         |