icy-arctic-fox / spectator

Feature-rich testing framework for Crystal inspired by RSpec.
https://gitlab.com/arctic-fox/spectator
MIT License
103 stars 5 forks source link

Attempting to mock File results in error #49

Open watzon opened 1 year ago

watzon commented 1 year ago

Not sure if this is part of the intended purpose of mocks or not, but I'm attempting to mock the File class and I get the following error:

...
 > 38 |         # Attempt to find a stub that satisfies the method call and arguments.
 > 39 |         # Finding a suitable stub is delegated to the type including the `Stubbable` module.
 > 40 |         if __temp_270 = _spectator_find_stub(__temp_269)
 > 41 |           # Cast the stub or return value to the expected type.
 > 42 |           # This is necessary to match the expected return type of the original method.
 > 43 |           _spectator_cast_stub_value(__temp_270, __temp_269, typeof(previous_def(prefix, suffix, *dir: direncoding: encodinginvalid: invalid) { |*_spectator_yargs| yield *_spectator_yargs }),
 > 44 |           :raise)
 > 45 |         else
 > 46 |           # Delegate missing stub behavior to concrete type.
 > 47 |           _spectator_stub_fallback(__temp_269, typeof(previous_def(prefix, suffix, *dir: direncoding: encodinginvalid: invalid) { |*_spectator_yargs| yield *_spectator_yargs })) do
 > 48 |             # Use the default response for the method.
 > 49 |             previous_def(prefix, suffix, *dir: direncoding: encodinginvalid: invalid) { |*_spectator_yargs| yield *_spectator_yargs }
 > 50 |           end
 > 51 |         end
 > 52 |       end
 > 53 |     
Error: unexpected token: "direncoding"
watzon commented 1 year ago

Traced the issue to stubbable.cr, line 129-164. Seems like there are some cases that it's not handling well.

icy-arctic-fox commented 1 year ago

The original issue has been resolved, however there's another issue that prevents mocking File. The compiler does not allow casting a union of a pointer and nil to non-nil. For instance:

a = true ? Pointer(UInt8).null : nil
b = a.as(Pointer(UInt8))
p! a, typeof(a), b, typeof(b)

I'm not sure if this is intended or a bug in the compiler. This code works for other non-pointer types.

https://gitlab.com/arctic-fox/spectator/-/jobs/3648109240#L35

https://github.com/crystal-lang/crystal/issues/13000

watzon commented 1 year ago

Ahh that's what that question was in reference to

icy-arctic-fox commented 1 year ago

It doesn't appear that the issue with pointers in unions will be fixed soon. A workaround in Spectator would be substantial. There's a possible fix that may even reduce compilation time, but it could take a while to implement.

Sija commented 4 weeks ago

Was this issue finally resolved?

icy-arctic-fox commented 2 weeks ago

I don't think it has been resolved. This issue is the root cause. Reworking Spectator to use a different storage method, that doesn't use unions of pointers, would fix the issue. Mocks have been extracted to their own shard. This issue shouldn't be present in that shard. Eventually Spectator will be updated to use the mocks shard. The mock injection feature should support mocking of File.