jqwik-team / jqwik

Property-Based Testing on the JUnit Platform
http://jqwik.net
Eclipse Public License 2.0
576 stars 64 forks source link

Mockito Support (includes link to working code) #605

Open agustafson-atl opened 2 weeks ago

agustafson-atl commented 2 weeks ago

Testing Problem

It would be great if a jqwik test could integrate with Mockito as easily as JUnit does.

Suggested Solution

I've put together the code for it here: https://github.com/agustafson-atl/jqwik-mockito/ I'm happy for it to be moved under the jqwik github account if possible. Otherwise I can move it to my company's account.

Discussion

This would allow users to use jqwik in more situations, which would be great.

jlink commented 2 weeks ago

Worthwhile idea to scrutinise. But the link does not work: 404.

agustafson-atl commented 2 weeks ago

Ah it helps if I make the repository public! 🤦   I've made it public now and can confirm that it's now visible. Thanks for taking a look so quickly @jlink - appreciate it.

jlink commented 2 weeks ago

I wonder if it would make sense if the lifecycle hook would be symmetrical to Mockito‘s Jupiter extension - as far as possible. This would it easy for Jupiter users to reuse their knowledge. What do you think, @agustafson-atl ?

agustafson-atl commented 2 weeks ago

Thanks for the feedback @jlink but I'm not sure what that would mean practically? As in, we should allow user to add a @ExtendsWith(MockitoLifecycleHooks.class) annotation to their class instead of @AddLifecycleHook(MockitoLifecycleHooks.class)? Or you can see that there are gaps/differences between the MockitoLifecycleHooks and what Mockito's Jupiter extension provides?

Either way, I'm happy to make the transition simple for users to go from JUnit to jqwik. My hope was that we could just replace:

jlink commented 2 weeks ago

What I mean is that the jqwik hook should do the same things as the jupiter extension. If I understand your code correctly, all it does is reset mocks after each try, whereas the extension does more (eg initialise @Mock variables). But I may be missing something.

Have you looked at the extension’s implementation? Most of the code should be in the hook as well.

agustafson-atl commented 1 week ago

Ah, ok I can take a look to see what the extension does - good idea thanks.

My code is currently initialising Mockito annotated elements on this line: https://github.com/agustafson-atl/jqwik-mockito/blob/main/src/main/java/net/jqwik/mockito/MockitoLifecycleHooks.java#L65

I can take a look at the Mockito extension, but I've added test cases which include:

I wanted to cover off any use cases that I knew about, and I think every case should be adequately covering them off.

jlink commented 1 week ago

Looking at https://github.com/JeffFaer/junit5-extensions/blob/master/mockito-extension/src/main/java/name/falgout/jeffrey/testing/junit/mockito/MockitoExtension.java I see two aspects that your hook does not cover (yet):

And there's one thing that brings an additional complexity to properties: Should mocks be reset per try or per property? I haven't deeply thought about it, but it might make sense to have that as a configuration parameter to choose one or the other.

jlink commented 1 week ago

And sorry for suggesting too many changes. If you think you're done, that's good with me. We can then consider moving it to @junit-team and making it an official extension.

agustafson-atl commented 1 week ago

I did wonder about the mocks potentially resetting per property or per try, but I couldn't realistically think of a reason why anybody would want to maintain state across multiple tries. But for completeness I imagine that would be an improvement. I hadn't thought about the other concerns you'd raised. I'll take a look into them.

I hadn't considered to make it a JUnit extension as it's using jqwik and Mockito. But if you think that makes more sense then I can do that. Would I just replicate the issue in their repo and reference this issue?

Don't worry for suggesting the changes - appreciate it!

jlink commented 1 week ago

Not a JUnit extension. A jqwik extension. My wording was misleading. This would entail bringing it to jqwik-team and publishing it as a jqwik artefact.

agustafson-atl commented 1 week ago

Ok, gotcha. A jqwik extension makes sense.

I'll look into the issues you raised. Looking at the MockitoExtension I can see it has support for @Strictness as well, so I'll attempt to add some extra functionality based on the MockitoExtension.

I may have to get approval from my company to open-source this as they have a policy regarding contributions. Will update this issue once I've got more info and code is updated.

agustafson-atl commented 12 hours ago

Hi, I've kicked off the open-sourcing process with my company and that should be approved soonish.

I've also updated/fixed the lib so that it uses a Store to keep track of mocks rather than storing them as a field. That should support parallelisation.

I also tried to work out how to cover the missing functionality that you raised, ie:

Thanks!