Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot seem to test when new is called #32

Closed
postmodern opened this issue Jul 3, 2021 · 7 comments
Closed

Cannot seem to test when new is called #32

postmodern opened this issue Jul 3, 2021 · 7 comments
Assignees
Labels
bug Something isn't working feedback-requested Information wanted from the original poster
Milestone

Comments

@postmodern
Copy link

Ran into this when porting RSpec tests which stubs the new method so that the tests control the instance object that's returned.

require "./spec_helper"

Spectator.describe Test do
  module TestFoo
    class TestClass
      def initialize
      end

      # the method we are testing
      def self.test
        new().test
      end

      # the method we want to ensure gets called
      def test
      end
    end
  end

  let(test_class) { TestFoo::TestClass }
  let(test_instance) { test_class.new }

  describe "something else" do
    mock TestFoo::TestClass do
      stub new
    end

    it "must test when new is called" do
      expect(test_class).to receive(:new).with(no_args).and_return(test_instance)
      expect(test_instance).to receive(:test)

      test_class.test
    end
  end
end
Test
  something else
    must test when new is called

Failures:

  1) Test something else must test when new is called
     Failure: test_class did not receive #new(#<Spectator::Mocks::NoArguments:0x7f3fba62cbe0>) : SpectatorTest::Context__temp_27::TestFoo::TestClass at spec/test_spec.cr:27 at least once with any arguments

       expected: At least once with any arguments
       received: 0 time(s)

     # spec/test_spec.cr:26

Finished in 466 microseconds
1 examples, 1 failures, 0 errors, 0 pending
@icy-arctic-fox icy-arctic-fox self-assigned this Jul 8, 2021
@icy-arctic-fox icy-arctic-fox added the bug Something isn't working label Jul 8, 2021
@icy-arctic-fox
Copy link
Owner

icy-arctic-fox commented Jul 8, 2021

Since new is a class method, the stub name should have a self. prefix.

mock TestFoo::TestClass do
  stub self.new
end

But... looks like when I implemented the fix for stubbing exit, a bug was introduced that prevents this from working.

icy-arctic-fox added a commit that referenced this issue Jul 11, 2021
@icy-arctic-fox
Copy link
Owner

Should be resolved in v0.9.40, can you verify?

Needs to be mocked by using stub self.new (the self. prefix is required since .new is a class method).

@icy-arctic-fox icy-arctic-fox added the feedback-requested Information wanted from the original poster label Jul 16, 2021
@postmodern
Copy link
Author

Now I'm curious how one would stub self.new, but have it return a copy of the class? This is to to ensure that new is called under the hood by the class-method which one is testing, and to control the value new returns so one can expect(instance).to receive(...).

@postmodern
Copy link
Author

Also having trouble stubbing File.file?.

      mock File do
        stub self.file?, path : String, return_type: Bool
      end

      before_each do
        expect(File).to receive(:file?).with("/etc/fedora-release").and_return(true)
      end

      it { expect(subject.linux_distro).to be(CommandKit::OS::Linux::LinuxDistro::Fedora) }
  1) CommandKit::OS::Linux.linux_distro and the /etc/fedora-release file exists subject.linux_distro is CommandKit::OS::Linux::LinuxDistro::Fedora
     Failure: File did not receive #file?("/etc/fedora-release") : Bool at spec/os/linux_spec.cr:22 at least once with any arguments

       expected: At least once with any arguments
       received: 0 time(s)

I think that error message is slightly misleading, since I'm not expecting the #file? instance method, but the class-method.

@icy-arctic-fox
Copy link
Owner

The error is misleading, I think it's hard-coded to prefix stubbed method names with # despite it being a class method.

Can you try this code with latest master branch? There was a fix made the other day that might address it.

@icy-arctic-fox icy-arctic-fox added this to the v0.11 milestone Mar 17, 2022
@icy-arctic-fox
Copy link
Owner

This functionality has been verified to work in the overhauled mock system. See the spec related to this issue for its implementation. This is coming in v0.11 and is currently available on master for testing.

Note that this uses inject_mock, which is modify the existing types. They should behave the same as before, but their underlying code will have stub features added. This results in different compiled code for the type between test and non-test.

@icy-arctic-fox
Copy link
Owner

This issue should be resolved in v0.11. There is a spec dedicated to it. If your issue isn't resolved, please reopen this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working feedback-requested Information wanted from the original poster
Projects
None yet
Development

No branches or pull requests

2 participants