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

Add support for Scala 3 #364

Open
ultrasecreth opened this issue Feb 24, 2021 · 17 comments
Open

Add support for Scala 3 #364

ultrasecreth opened this issue Feb 24, 2021 · 17 comments

Comments

@ultrasecreth
Copy link
Member

Scala 3 has a ton of changes on the internals and more importantly, the macros.
mockito-scala makes heavy use of macros, reflection and it also relies on knowing how certain features are compiled/implemented so they can run in the JVM.

This means that pretty much a new lib has to be written for dotty.

My current line of thinking is that we need to:

  1. Implement the basic features for dotty in a separate branch/repo
  2. Dive in with the more complex ones
  3. Split out the public API from the existing project as a separate module
  4. Make the existent lib and the new one use and implement the new public API, so people can use them interchangeably and migrations are easier.
  5. Profit(?) :)
@ultrasecreth
Copy link
Member Author

This replaces #330

@tOverney
Copy link

Scala 3 first official version got released yesterday: https://github.com/lampepfl/dotty/releases/tag/3.0.0
:)

@ultrasecreth
Copy link
Member Author

Yeah, my main blocker is the tooling, I really need good debugging tools to reverse engineer what mockito and/or the scala compiler does and I found that almost impossible at the moment.
This is almost blocked I'd say until IntelliJ or any other real IDE has proper support for Scala 3 :(

@dotordogh
Copy link

Hi @bbonanno! We at Twitter are actively trying to cross-build our Util library (https://github.com/twitter/util) with Scala 3. We use mockito-scala in a base subproject that many others depend on. We've identified that we depend on ArgumentMatchersSugar and IdiomaticMockito in mockito-scala and depend on much more in mockito-scala-scalatest. Do you have an estimate for when we might be able to expect support for Scala 3?

In the meantime, I'm looking at potentially using 2.13-specific versions for mockito-scala and mockito-scala-scalatest for the Scala 3 crossbuild, but I'm still not sure how that will pan out. I will comment when I know more.

cc @NataliaMGonzalez @hamdiallam

@ultrasecreth
Copy link
Member Author

Hi @dotordogh,
Sadly the sorry state of affairs on the Scala 3 tooling is blocking me on the development of the Scala 3 version, last 2 times I tried I hit the hard wall of not having a fully functional IDE, that allows me to debug and reverse engineer what the Scala 3 compiler does.
At the time the consensus was to use print lines to "debug", but that doesn't cut it for me as I need to see how the Scala constructs reach the Java core of Mockito, which is key for me to bridge the gap and make everything work.
I plan to have another go probably by the end of the month, but if the tooling is still in the same sorry state I'm not sure if I'll manage to do anything meaningful.

If you, and anybody else that's looking to migrate, can outline the features that are deemed the most important, I can try to focus on those first and hopefully release a "lite" version whilst the bulk of the features are still being developed.

I'd also be very interested to see how did it go using the 2.13 version for the cross-build :)

Cheers!

@dotordogh
Copy link

@bbonanno Got it! Thank you for responding! I did see you mention that the IDE support for Scala 3 was subpar, but I was mainly wondering if things had improved since then.

I did try it with the 2.13 version and it seems to work fine for the cross-build, so we'll stick with that until we can upgrade.

@NataliaMGonzalez or I can provide you with a list of features that we use in the coming week to help inform a "lite" release.

Thank you again! We really appreciate it!

@NataliaMGonzalez
Copy link

Hi @bbonanno we have identified that this are the features we depend on:

  • For idiomaticMockito, ArgumentMatchersSugar, ArgCaptor, CallsRealMethod, DefaultAnswer and ResetMocksAfterEachTest we need the full feature set;
  • With MockitoSugar we use verify and when;
  • And for ScalaFirstStubbing we use thenReturn

Thanks again for all your help!

@ultrasecreth
Copy link
Member Author

Yeah, pretty much anything that uses macros :(
Will give it a go again as soon as I have some free time (quite scarce lately)
Sorry about the wait!

@jveldhuizen
Copy link

jveldhuizen commented Jan 18, 2022

Hi @bbonanno, do you have any news about this?

@ultrasecreth
Copy link
Member Author

@jveldhuizen I'm afraid not, I've been pretty busy at work and had 0 time.
Maybe someone in the community wants to step up? (would be also nice to raise the bus factor to at least 2)

@jrgleason
Copy link

Any update?

@ultrasecreth
Copy link
Member Author

I'm afraid I'm not actively developing the lib anymore, just basic maintenance atm, so no clear path to get a Scala 3 version any time soon...
Happy to guide contributors if anyone wants to step in

jnatten added a commit to NDLANO/backend that referenced this issue Feb 22, 2023
Since `mockito-scala` seems to be non-active, lets try another mockito
wrapper.

Source: mockito/mockito-scala#364 (comment)
jnatten added a commit to NDLANO/backend that referenced this issue Feb 22, 2023
Since `mockito-scala` seems to be non-active, lets try another mockito
wrapper.

Source: mockito/mockito-scala#364 (comment)
pandurangpatil pushed a commit to Privado-Inc/privado-core that referenced this issue Jul 11, 2023
* Scala 3 Upgrade
Upgraded Joern and as minimal dependencies as possible to their compatible Scala 3 variant.

Note: [Mockito has no Scala 3 compatibility](https://index.scala-lang.org/mockito/mockito-scala) (yet) so we will have to disable it or find an alternative. The bad news is that this project has no clear path to [Scala 3](mockito/mockito-scala#364 (comment))

* Removing Mockito

* Updated Scala format to Scala 3

* Removed Scala 2.13 spec from code quality workflow

* Fixed Scala 3 compilation issues

* removed snakeyaml dependency

---------

Co-authored-by: “Hitesh <[email protected]>
@jozic
Copy link
Contributor

jozic commented Jul 24, 2023

@ultrasecreth has anything change since last update? there are still no plans to support Scala 3, right?
Do you know what level of effort is required there? Have you tried estimating it?
Thanks!

@AlexITC
Copy link

AlexITC commented Jul 24, 2023

I understand that mockito-scala depends heavily on macros, migrating the code to scala3 isn't likely trivial.

https://github.com/fmonniot/scala3mock is an alternative which you could consider, in our case, we ended up using java mockito.

@henricook
Copy link

@AlexITC

in our case, we ended up using java mockito.

Would love to read a 'how to convert' style blog post if you find yourself so motivated! Is it ugly?

@gaeljw
Copy link

gaeljw commented Jan 30, 2024

We also moved to pure Mockito and/or ScalatestPlus-Mockito. Relatively easy but I guess we were not strongly relying on Mockito scala's specific feature.

@henricook
Copy link

henricook commented Jan 30, 2024

EDITED: To add a mock and lazy doNothing method

I've actually just done this, it really was quite easy, but we weren't using mockito-scala matchers. So most of our matchers were already java friendly, and it was mostly just changing mock[Class] to mock(classOf[Class]) and imports

I found that I had to implement a special matcher for Option argument matchers, here it is in case it helps anyone else (or if anyone else has a better way!)

import org.mockito.ArgumentMatchers.argThat
import org.mockito.Mockito
import org.mockito.stubbing.{Answer, Stubber}

import scala.reflect.ClassTag

/** Minimal helper functions to make Java Mockito slightly more scala
  */
object CustomMockito {

  // This method might struggle to mock complex generic types due to type erasure. If experiencing issues
  // Try using Mockito.mock directly with mock[MyClass]
  def mock[T: ClassTag]: T = Mockito.mock(implicitly[ClassTag[T]].runtimeClass.asInstanceOf[Class[T]])

  def mock[T: ClassTag](defaultAnswer: Answer[Object]): T =
    Mockito.mock(implicitly[ClassTag[T]].runtimeClass.asInstanceOf[Class[T]], defaultAnswer)

  object Stubber {
    def doNothing: Stubber = Mockito.doNothing()
  }

  object Matchers {

    def someMatcher[T]: Option[T] = argThat((arg: Option[T]) =>
      arg match {
        case null    => false // Java interop
        case None    => false
        case Some(_) => true
      }
    )

    def noneMatcher[T]: Option[T] = argThat((arg: Option[T]) =>
      arg match {
        case null => true // Java interop
        case None => true
        case _    => false
      }
    )
  }
}

Usage like:

...
someMatcher[String]
noneMatcher[String]
doNothing
mock[MyClass]
mock[MyClass](Answers.RETURNS_SMART_NULLS)
...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants