dart-lang / mockito

Mockito-inspired mock library for Dart
https://pub.dev/packages/mockito
Apache License 2.0
623 stars 160 forks source link

Freezed models can't be mocked without json_serializable #689

Open Senne021 opened 10 months ago

Senne021 commented 10 months ago

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.

yanok commented 10 months ago

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

Mark-Toten commented 10 months ago

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 commented 10 months ago

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

natebosch commented 10 months ago

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.

yanok commented 10 months ago

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?

jakemac53 commented 10 months ago

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

natebosch commented 10 months ago

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.

Mark-Toten commented 10 months ago

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.