paulbutcher / ScalaMock

Native Scala mocking framework
http://scalamock.org/
MIT License
501 stars 98 forks source link

Scala 3 #490

Closed goshacodes closed 5 months ago

goshacodes commented 10 months ago

Pull Request Checklist

Purpose

Migration to Scala 3.

Write additional tests for:

Migration notes:

  1. Methods without parameters should be represented as function (Scala 3 restriction)
    
    trait Turtle:
    def getAngle: Double

val t = mock[Turtle]

// this one no longer compiles (t.getAngle _).expects(*).returns(1.0)

// this one should be used instead (() => t.getAngle).expects(*).returns(1.0)

2. Type should be specified for methods with by-name parameters
```scala
trait TestTrait:
  def byNameParam(x: => Int): String

val t = mock[TestTrait]

// this one no longer compiles
(t.byNameParam _).expects(*).returns("")

// this one should be used instead
(t.byNameParam(_: Int)).expects(*).returns("")
  1. Vars support becomes super scarse Abstract vars are not supported anymore, use scala.compiletime.uninitialized instead. There are multiple issues when trying to override vars, so mocking vars feature is dropped.
trait X:
  var y: Int  // No more compiles
  var y: Int = scala.compile.uninitialized // Should be used instead 
  1. Java class mocking is not available without workaround
public class JavaClass {
    public int simpleMethod(String b) { return 4; }
}
val m = mock[JavaClass] // not works anymore

class JavaClassExtended extends JavaClass

val mm = mock[JavaClassExtended] // should be used instead
lrytz commented 10 months ago

Facing this one right now

Is this problem still current?

goshacodes commented 10 months ago

No, it is fixed

Facing this one right now

Is this problem still current?

goshacodes commented 10 months ago

I'm superbusy till next wednesday. If someone want to help, I can add a collaborator to my fork telegram: @georgiikov discord: @goshacodes

tmccombs commented 8 months ago

Anything I can do to help?

kovalyovGA commented 7 months ago

@tmccombs Hi. I've found a problem after resolving all tests. I need to rewrite path dependent types support, but I don't sure how for now. This is not working, as I remember. And also more nested structures with path dependent types:

trait Foo:
   trait Bar
   trait Baz[T]
  def foo(x: Option[Bar]): Option[Bar]
  def bar(x: Baz[Bar]): Baz[Bar]

And I have no time :(

goshacodes commented 7 months ago

I've solved last issue

goshacodes commented 7 months ago

@paulbutcher @barkhorn Hi guys, I need to run new workflow, merge and publish candidate

paulbutcher commented 7 months ago

I'm afraid that I handed the reigns entirely over to Philipp some while ago.

barkhorn commented 7 months ago

Might need to revisit that situation. Iโ€™ve not been using Scala for some years now so the focus was just on small dependency updates and contributed patches. Itโ€™s nice to see people porting it to Scala 3 for sure!

barkhorn commented 7 months ago

Kicked off the workflow

goshacodes commented 7 months ago

So what do we do? I think you can make me a collaborator, so I'll handle everything myself

paulbutcher commented 7 months ago

@barkhorn are you OK with passing access along to @goshacodes? He's showing willing which is a good start ๐Ÿ˜œ

goshacodes commented 7 months ago

@barkhorn I summon you ๐Ÿ˜„ pokemon ball image

barkhorn commented 7 months ago

so this means we will drop support for Scala 2.11, right? Is that still widely used? I.e. Spark always lagged behind in Scala adoption but i've not been following that for some time, it may have changed

barkhorn commented 7 months ago

I think it would be good to add more collaborators to the project. Admin is still with @paulbutcher so I can't do that myself, but happy to PR review and merge stuff too for now. If we drop support for any Scala 2.x and require a breaking change for the Java subclasses then this should be a new major version (6.0.0) too before we release it

goshacodes commented 7 months ago

Since there were no changes for 2 years, I think it is stable enough to leave it as it is. I would also drop 2.12 for same reason (No reason to publish new candidates without changes). 2.13 should be dropped after 3+ will be stable enough (2.13 can use 3+ version)

so this means we will drop support for Scala 2.11, right?

Is that still widely used? I.e. Spark always lagged behind in Scala adoption but i've not been following that for some time, it may have changed

goshacodes commented 7 months ago

Let's use major version. Java subclasses really look like a dead end for now (I've tried to make workaround again, but it doesn't work), so there is no other options

I think it would be good to add more collaborators to the project. Admin is still with @paulbutcher so I can't do that myself, but happy to PR review and merge stuff too for now.

If we drop support for any Scala 2.x and require a breaking change for the Java subclasses then this should be a new major version (6.0.0) too before we release it

goshacodes commented 7 months ago

@barkhorn ?

barkhorn commented 7 months ago

Does Scala have a specific deprecation roadmap? https://www.scala-lang.org/download/all.html 2.13 is still under "current releases" so that should be kept at least imo. But if the library is universal to 2.13/3.x then can it be combined into one release? From what I remember, sbt appended the scala version when resolving the dependency so it should come out as two separate jar files, or has this changed?

mkurz commented 7 months ago

Does Scala have a specific deprecation roadmap?

I am not aware of that for Scala 2.13, AFAIK nothing was announced yet to deprecate Scala 2.x

But if the library is universal to 2.13/3.x then can it be combined into one release?

Yes, it always was and still is possible to cross compile a Scala project to target different Scala major releases (2.12, 2.13, 3)

From what I remember, sbt appended the scala version when resolving the dependency so it should come out as two separate jar files, or has this changed?

No nothing changed. Look at https://repo1.maven.org/maven2/org/scalamock/ for example there is scalamock_2.12, scalamock_2.13, etc. when you cross publish for scala 3 it appends _3 so that would be scalamock_3 then.

SethTisue commented 7 months ago

I am not aware of that for Scala 2.13, AFAIK nothing was announced yet to deprecate Scala 2.x

We expect to keep doing Scala 2.13.x releases indefinitely, as needed. (2.12.x is less certain, but we wouldn't ever EOL it without lengthy and well publicized notice.)

I think you should not have any qualms about dropping 2.11 support whenever. Anyone who's still stuck on 2.11 ought to be okay also remaining stuck on already-published versions of their dependencies, especially test dependencies like ScalaMock.

2.12 is in a sort of middle zone where some libraries have dropped support but many have not.

barkhorn commented 7 months ago

Thanks Seth that is really helpful! I propose following the same pattern for ScalaMock then, keeping 2.13 support and dropping earlier versions.

I'll create a maintenance branch in case any critical bugfixes need to be done for 2.12 in the future but it'll speed up builds to drop it in master.

goshacodes commented 6 months ago

@barkhorn Pinging just to be sure you didnโ€™t forgot

barkhorn commented 6 months ago

forget what?

goshacodes commented 6 months ago

I thought you've decided to finish what's left by yourself ๐Ÿค” No?

barkhorn commented 6 months ago

No, I have no intention of taking this PR over. Once it's ready to be reviewed and merged, I can release a version to Sonatype though, but I don't want to work on the code.

goshacodes commented 6 months ago

Let's review it then ๐Ÿ˜ƒ I won't since it's mine

kovalyovGA commented 6 months ago

What should be thoroughly reviewed:

  1. MockMaker.scala

  2. MockFunctionFinder.scala

  3. Utils.scala

The main idea of MockMacker is to generate this:

class $anon extends TestTrait {
    def <init>() = {
      super.<init>();
      ()
    };

    val mock$special$mockName = new scala.Predef.String("suite mock");

    override def polymorphicMethod[T](x: List[T]): String = $anon.this.mock$polymorphicMethod$0.apply(x);

    override def oneParamMethod(param: Int): String = $anon.this.mock$oneParamMethod$0.apply(param);

    override def noParamMethod(): String = $anon.this.mock$noParamMethod$0.apply();

    val mock$polymorphicMethod$0: MockFunction1[List[T], String] = new MockFunction1[List[T], String](TestedSuite.this._factory, scala.Symbol.apply(scala.Predef.augmentString("<%s> %s%s.%s%s").format($anon.this.mock$special$mockName, "TestTrait", "", "polymorphicMethod", "[T]")));

    val mock$oneParamMethod$0: MockFunction1[Int, String] = new MockFunction1[Int, String](TestedSuite.this._factory, scala.Symbol.apply(scala.Predef.augmentString("<%s> %s%s.%s%s").format($anon.this.mock$special$mockName, "TestTrait", "", "oneParamMethod", "")));

    val mock$noParamMethod$0: MockFunction0[String] = new MockFunction0[String](TestedSuite.this._factory, scala.Symbol.apply(scala.Predef.augmentString("<%s> %s%s.%s%s").format($anon.this.mock$special$mockName, "TestTrait", "", "noParamMethod", "")))
  };

  new $anon()

from this

trait TestTrait {
  def noParamMethod(): String
  def oneParamMethod(param: Int): String
  def polymorphicMethod[T](x: List[T]): String
}

The main idea of MockFunctionFinder is to find corresponding MockFunctionX in generated definition:

(testTrait.oneParamMethod _).when(*).returns("whatever")

When we call testTrait.oneParamMethod _ there is an implicit conversion from corresponding function to MockFunctionX, search is performed by corresponding macro

KuceraMartin commented 6 months ago

Hi, is someone working on the code review? Can we do something to help/facilitate it?

goshacodes commented 5 months ago

I guess nobody is going to review it, so we should leave it as it is and publish a candidate like M1 or RC1

goshacodes commented 5 months ago

@barkhorn

goshacodes commented 5 months ago

@barkhorn @paulbutcher Guys, all this is ridiculous, I think we can manage it without waiting another few years passing by

maxcom commented 5 months ago

Please release milestone artifacts with Scala 3 support.

SethTisue commented 5 months ago

I'm guessing the maintainers aren't seeing these notifications. Has anyone tried contacting them by other means?

barkhorn commented 5 months ago

I can take a look at the weekend, but don't have proper access to things at the moment. If anyone else wants to start put some comments in for now, that would be appreciated. Given the size of the change, would make sense to have some more eyes on it.

SethTisue commented 5 months ago

I noticed that the assertDoesNotCompile calls in the tests were commented out โ€”ย what's the reason for that?

goshacodes commented 5 months ago

I'll add a comment, thought I did.

https://github.com/scalatest/scalatest/issues/2283

henricook commented 5 months ago

Thanks for your activity here both, I was about to start writing scalamock out of my project to get to Scala 3 but what you're doing here gives me hope ๐Ÿ™๐Ÿป

barkhorn commented 5 months ago

A lot of work has clearly gone into that, thank for cleaning up in general. It looks good to me.

As a general comment, I think it would be great if the documentation could follow to explain any caveats with some of the changes. That doesn't have to be right now but I hope someone would pick that up.

goshacodes commented 5 months ago

Should I do anything else so we could proceed?

barkhorn commented 5 months ago

something has changed in one of the sbt plugins i think. couldn't release to sonatype just now because of missing signature (why is that even still a requirement...). I'll take a look over the coming days to push it out

barkhorn commented 5 months ago

released! :ship:

henricook commented 5 months ago

I'm probably just jumping the gun before the repositories have updated but it's:

"org.scalamock" %% "scalamock" % "6.0.0-M1" right?

barkhorn commented 5 months ago

it's on maven central as usual, so you can reference it the same way: https://central.sonatype.com/artifact/org.scalamock/scalamock_3

henricook commented 5 months ago

Thanks, I didn't have the _3 in my previous dep line

Edit: "org.scalamock" %% "scalamock" % "6.0.0-M1" eventually started working for 2.13 - I was just jumping the gun on the repository publishing the artifacts

rbscgh commented 4 months ago

great work @goshacodes! really uplifting news this got out ๐Ÿ’Ÿ