Q:

How to stub\mock instance in case statement? 

I have one class method, which use another one class instance method:
class Foo
  def foo
    # a lot of code here, which return String instance
  end
end

class Bar
  class UnknownType < StandardError;end 

  def initialize(foo)
    self.foo = foo
  end 

  attr_reader :foo 

  def call
    # some code which use method foo
    foo
  end

  private

  def foo=(attr)
    @foo ||= case attr
               when Foo then attr.foo
               when String then attr
               else raise UnknownType, "Unknown type #{attr.class.name}"
             end
  end

end

And my test doesn't work, I try to sub methods:
- is_a
- kind_of? 
let(:foo) { instance_double(Foo, foo: 'some text') }
let(:bar) { Bar.new(foo) }

subject { bar.call }

it 'make some business logic here' do
  expect { subject }.to be_truthy
end

But it raise error UnknownType becasue template is a #<InstanceDouble(Foo) (anonymous)>
not a Foo

A:

Case statements use === for case equality purposes and in this case Foo is the receiver not the argument.  e.g. 
  case attr
    when Foo then attr.foo
  end 

Compares attr to Foo as Foo === attr not the other way around. 
So you could change your test to 
it 'make some business logic here' do
  allow(Foo).to receive(:===).with(foo).and_return(true)
  expect { subject }.to be_truthy
end

This way when it evaluates your case statement it will follow the when Foo path because Foo === attr will be true due to the stubbing. 