mockito icon indicating copy to clipboard operation
mockito copied to clipboard

Freezed models can't be mocked without json_serializable

Open Senne021 opened this issue 2 years ago • 8 comments

I found a very strange behavior of mockito. If you generate a model with the freezed and want to mock it without adding the json_serializable as a dependency, the mocked freezed model is generated as an empty class and cannot be used.

This currently means that you have to add json_serializable as a dependency in a project, even if you don't need the actual package, just to make freezed and mockito work together.

Senne021 avatar Aug 24 '23 07:08 Senne021

Please create a sample (preferably minimal) project that makes it possible to reproduce the problem. I don't use freezed myself.

yanok avatar Aug 24 '23 12:08 yanok

Wow, thanks for discovering this! I can confirm this is a proper albeit dirty solution. For some months now I couldn't regenerate my mocks (and had to update the generated classes manually). I saw that part of the mocks are not generated without json_serializable included. It might have to do with the typedef that I use. I will create an example later today too.

Mark-Toten avatar Aug 24 '23 12:08 Mark-Toten

Here's a simple sample. Notice the different output when json_serializable is included. https://github.com/Mark-Toten/mockito_freezed

FWIW: I ran into this issue when trying to update from Mockito 5.2.0 to 5.4.0

Mark-Toten avatar Aug 24 '23 13:08 Mark-Toten

This may be an ordering issue? I'm not sure why adding an otherwise unrelated builder should force a different ordering, but it could. If mockito runs before freezed it won't see the generated code. I'm a little surprised it doesn't complain about resolution errors if that is the case. Can you check the order of the builders in the generated .dart_tool/build/entrypoint/build.dart file and report the ordering of mockito and freezed between when it works and doesn't work?

I don't think it's sensible to add a required_inputs here, but it also doesn't seem like a healthy coupling if freezed needs to add a runs_before either. @jakemac53 - what is our current best practice for this situation? I wonder if we are missing some way for end users to give a hint about this in their config without doing a full override of the config...

It might also work to split the test directory into a separate target which depends on the library target. As long as the freezed models are in lib/, and the mockito usage is in test/, the target ordering might resolve the problem. Having to add targets for this is not very discoverable, and feels like a cliff from having a config with implicit targets.

natebosch avatar Aug 24 '23 23:08 natebosch

Yes, this is an ordering issue: without json_serializable mockBuilder runs before freezed. json_serializable helps because freezed explicitly requests running before json_serializable https://github.com/rrousselGit/freezed/blob/7e478b841f247b8fb0a95722a88392950df22489/packages/freezed/build.yaml#L25

I don't know though, what makes mockBuilder run after json_serializable.

I'll leave to @jakemac53 to comment, what would be possible ways to fix it (except for asking freezed to add another runs_before clause).

But I have a general question: freezed objects are immutable values with no behavior, why would you even want to mock them?

yanok avatar Aug 25 '23 12:08 yanok

We do support a global_options config to affect ordering for a given package (without overriding builder configs), see https://github.com/dart-lang/build/blob/master/docs/faq.md#how-can-i-adjust-builder-ordering

jakemac53 avatar Aug 25 '23 14:08 jakemac53

But I have a general question: freezed objects are immutable values with no behavior, why would you even want to mock them?

This is a good point - mocking a data model is not a good practice.

natebosch avatar Aug 25 '23 16:08 natebosch

But I have a general question: freezed objects are immutable values with no behavior, why would you even want to mock them?

In my case the classes used to be regular classes which I migrated to immutable freezed classes. The unittests where written for the original classes and didn't need change after this migration, since Mockito generated fine classes up until Mockito 5.2.0.

Mark-Toten avatar Aug 28 '23 21:08 Mark-Toten