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

Scala 3 #490

Merged
merged 18 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions .github/workflows/scala.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,6 @@ on:
branches: [ master ]

jobs:
scala_2_11:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: 11
distribution: 'adopt'
- name: Run tests
run: sbt ++2.11.12 test

scala_2_12:

runs-on: ubuntu-latest
Expand Down Expand Up @@ -48,3 +34,17 @@ jobs:
distribution: 'adopt'
- name: Run tests
run: sbt ++2.13.12 test

scala_3:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
goshacodes marked this conversation as resolved.
Show resolved Hide resolved
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: 11
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is JDK 11 still the best runtime?
17/21 are available as LTS versions now but the class-version may be too high for Scala?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we can user latter version

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Play framework still supports JDK 11 and I use ScalaMock in a library released for Play, it would be awesome supporting JDK 11 for a while

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left 11

distribution: 'adopt'
- name: Run tests
run: sbt ++3.3.0 test
48 changes: 30 additions & 18 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
import sbtcrossproject.CrossPlugin.autoImport.crossProject

ThisBuild / scalaVersion := "2.11.12"
ThisBuild / crossScalaVersions := Seq("2.11.12", "2.12.18", "2.13.12")
//ThisBuild / scalaJSUseRhino := true

lazy val scalatest = Def.setting("org.scalatest" %%% "scalatest" % "3.2.17")
lazy val specs2 = Def.setting("org.specs2" %%% "specs2-core" % "4.10.6")
lazy val specs2 = Def.setting("org.specs2" %%% "specs2-core" % "4.20.2")

val commonSettings = Defaults.coreDefaultSettings ++ Seq(
Compile / unmanagedSourceDirectories ++= {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2L, minor)) =>
Some(baseDirectory.value.getParentFile / s"shared/src/main/scala-2.$minor")
case _ =>
None
}
},
scalacOptions ++= Seq("-deprecation", "-unchecked", "-feature", "-Xcheckinit", "-target:jvm-1.8")
scalaVersion := "3.3.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
scalaVersion := "3.3.0",
scalaVersion := "3.3.1",

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a bug in 3.3.0 which allows us not to use @experimental on every test suite. I think we should use it.

Copy link
Contributor

@SethTisue SethTisue Feb 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth a comment, then.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

scalacOptions ++= Seq("-deprecation", "-unchecked", "-feature", "-release:8")
)

lazy val scalamock = crossProject(JSPlatform, JVMPlatform) in file(".") settings(
commonSettings,
crossScalaSettings,
name := "scalamock",
Compile / packageBin / publishArtifact := true,
Compile / packageDoc / publishArtifact := true,
Expand All @@ -29,21 +19,43 @@ lazy val scalamock = crossProject(JSPlatform, JVMPlatform) in file(".") settings
Compile / doc / scalacOptions ++= Opts.doc.title("ScalaMock") ++
Opts.doc.version(version.value) ++ Seq("-doc-root-content", "rootdoc.txt", "-version"),
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
scalatest.value % Optional,
specs2.value % Optional
)
)

lazy val `scalamock-js` = scalamock.js
lazy val `scalamock-jvm` = scalamock.jvm

lazy val examples = project in file("examples") settings(
commonSettings,
crossScalaSettings,
name := "ScalaMock Examples",
publish / skip := true,
libraryDependencies ++= Seq(
scalatest.value % Test,
specs2.value % Test
)
) dependsOn scalamock.jvm

def crossScalaSettings = {
def addDirsByScalaVersion(path: String): Def.Initialize[Seq[sbt.File]] =
scalaVersion.zip(baseDirectory) { case (v, base) =>
CrossVersion.partialVersion(v) match {
case Some((v, _)) if Set(2L, 3L).contains(v) =>
Seq(base / path / s"scala-$v")
case _ =>
Seq.empty
}
}
Seq(
crossScalaVersions := Seq("2.12.18", "2.13.11", scalaVersion.value),
goshacodes marked this conversation as resolved.
Show resolved Hide resolved
Compile / unmanagedSourceDirectories ++= addDirsByScalaVersion("src/main").value,
Test / unmanagedSourceDirectories ++= addDirsByScalaVersion("src/test").value,
libraryDependencies ++= {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, _)) =>
Seq("org.scala-lang" % "scala-reflect" % scalaVersion.value)
case _ =>
Seq.empty
}
}
)
}
6 changes: 3 additions & 3 deletions examples/src/test/scala/com/example/ControllerTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ class ControllerTest extends AnyFunSuite with MockFactory {
inSequence {
inAnyOrder {
(() => mockTurtle.penUp()).expects()
(mockTurtle.getPosition _).expects().returning(0.0, 0.0)
(mockTurtle.getAngle _).expects().returning(0.0)
(() => mockTurtle.getPosition).expects().returning(0.0, 0.0)
(() => mockTurtle.getAngle).expects().returning(0.0)
}
(mockTurtle.turn _).expects(~(Pi / 4))
(mockTurtle.forward _).expects(~sqrt(2.0))
(mockTurtle.getAngle _).expects().returning(Pi / 4)
(() => mockTurtle.getAngle).expects().returning(Pi / 4)
(mockTurtle.turn _).expects(~(-Pi / 4))
(() => mockTurtle.penDown()).expects()
(mockTurtle.forward _).expects(1.0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ class HigherOrderFunctionsTest extends AnyFreeSpec with MockFactory {
val f = mockFunction[Int, String]

inSequence {
f expects (1) returning "one" once;
f expects (2) returning "two" once;
f expects (3) returning "three" once;
f.expects(1).returning("one").once();
f.expects(2).returning("two").once();
f.expects(3).returning("three").once();
}

assertResult(Seq("one", "two", "three")) {
Expand All @@ -61,10 +61,10 @@ class HigherOrderFunctionsTest extends AnyFreeSpec with MockFactory {
val f = mockFunction[String, Int, String]

inSequence {
f expects("initial", 0) returning "intermediate one" once;
f expects("intermediate one", 1) returning "intermediate two" once;
f expects("intermediate two", 2) returning "intermediate three" once;
f expects("intermediate three", 3) returning "final" once;
f.expects("initial", 0).returning("intermediate one").once();
f.expects("intermediate one", 1).returning("intermediate two"). once();
f.expects("intermediate two", 2).returning("intermediate three").once();
f.expects("intermediate three", 3).returning("final").once();
}

assertResult("final") {
Expand Down
6 changes: 3 additions & 3 deletions examples/src/test/scala/com/example/OrderSpecification.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ class OrderSpecification extends Specification {
"remove inventory when in stock" in new MockContext {
val mockWarehouse = mock[Warehouse]
inSequence {
(mockWarehouse.hasInventory _).expects("Talisker", 50).returning(true).once
(mockWarehouse.remove _).expects("Talisker", 50).once
(mockWarehouse.hasInventory _).expects("Talisker", 50).returning(true).once()
(mockWarehouse.remove _).expects("Talisker", 50).once()
}
val order = new Order("Talisker", 50)
order.fill(mockWarehouse)
Expand All @@ -43,7 +43,7 @@ class OrderSpecification extends Specification {

"remove nothing when out of stock" in new MockContext {
val mockWarehouse = mock[Warehouse]
(mockWarehouse.hasInventory _).expects(*, *).returns(false).once
(mockWarehouse.hasInventory _).expects(*, *).returns(false).once()
val order = new Order("Talisker", 50)
order.fill(mockWarehouse)
order.isFilled must beFalse
Expand Down
4 changes: 2 additions & 2 deletions examples/src/test/scala/com/example/OrderTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ class OrderTest extends AnyWordSpec with MockFactory {
"remove inventory" in {
val mockWarehouse = mock[Warehouse]
inSequence {
(mockWarehouse.hasInventory _) expects ("Talisker", 50) returning true
(mockWarehouse.remove _) expects ("Talisker", 50) once
(mockWarehouse.hasInventory _).expects ("Talisker", 50).returning(true)
(mockWarehouse.remove _).expects("Talisker", 50).once()
}

val order = new Order("Talisker", 50)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class ReallySimpleExampleTest extends AnyFunSuite with MockFactory {
test("WithVariableParameters") {
val australianFormat = mock[Formatter]

(australianFormat.format _).expects(*).onCall { s: String => s"G'day $s" }.twice()
(australianFormat.format _).expects(*).onCall { (s: String) => s"G'day $s" }.twice()

Greetings.sayHello("Wendy", australianFormat)
Greetings.sayHello("Gray", australianFormat)
Expand All @@ -62,10 +62,10 @@ class ReallySimpleExampleTest extends AnyFunSuite with MockFactory {
}

// argAssert fails early
(formatter.format _).expects(argAssert(assertTeamNatsu _)).onCall { s: String => s"Yo $s" }.once()
(formatter.format _).expects(argAssert(assertTeamNatsu _)).onCall { (s: String) => s"Yo $s" }.once()

// 'where' verifies at the end of the test
(formatter.format _).expects(where { s: String => teamNatsu contains(s) }).onCall { s: String => s"Yo $s" }.twice()
(formatter.format _).expects(where { (s: String) => teamNatsu contains(s) }).onCall { (s: String) => s"Yo $s" }.twice()

Greetings.sayHello("Carla", formatter)
Greetings.sayHello("Happy", formatter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ class ControllerTest extends AnyFunSuite with MockFactory {

inSequence {
inAnyOrder {
(mockTurtle.getPosition _).when().returns(0.0, 0.0)
(mockTurtle.getAngle _).when().returns(0.0).once()
(() => mockTurtle.getPosition).when().returns(0.0, 0.0)
(() => mockTurtle.getAngle).when().returns(0.0).once()
}
(mockTurtle.getAngle _).when().returns(Pi / 4)
(() => mockTurtle.getAngle).when().returns(Pi / 4)
}

controller.drawLine((1.0, 1.0), (2.0, 1.0))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,18 @@ class HigherOrderFunctionsTest extends AnyFreeSpec with MockFactory {
"testMap" in {
val f = stubFunction[Int, String]

f when (1) returns "one"
f when (2) returns "two"
f when (3) returns "three"
f.when(1).returns("one")
f.when(2).returns("two")
f.when(3).returns("three")

assertResult(Seq("one", "two", "three")) {
Seq(1, 2, 3) map f
}

inSequence {
f verify (1) once;
f verify (2) once;
f verify (3) once;
f.verify(1).once();
f.verify(2).once();
f.verify(3).once();
}
}

Expand Down Expand Up @@ -74,10 +74,10 @@ class HigherOrderFunctionsTest extends AnyFreeSpec with MockFactory {
}

inSequence {
f verify("initial", 0) once;
f verify("intermediate one", 1) once;
f verify("intermediate two", 2) once;
f verify("intermediate three", 3) once;
f.verify("initial", 0).once();
f.verify("intermediate one", 1).once();
f.verify("intermediate two", 2).once();
f.verify("intermediate three", 3).once();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class OrderTest extends AnyWordSpec with MockFactory {
order.fill(mockWarehouse)

assert(order.isFilled)
(mockWarehouse.remove _) verify ("Talisker", 50) once
(mockWarehouse.remove _).verify("Talisker", 50).once()
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.paulbutcher.test.mock

import com.paulbutcher.test.TestTrait
import org.scalamock.function.FunctionAdapter1
import org.scalatest.matchers.should.Matchers
import org.scalamock.scalatest.MockFactory
import org.scalatest.freespec.AnyFreeSpec

class ByNameParametersTest extends AnyFreeSpec with MockFactory with Matchers {

autoVerify = false

"cope with methods with by name parameters" in {
withExpectations {
val m = mock[TestTrait]
(m.byNameParam _).expects(*).returning("it worked")
assertResult("it worked") { m.byNameParam(42) }
}
}

//! TODO - find a way to make this less ugly
"match methods with by name parameters" in {
withExpectations {
val m = mock[TestTrait]
val f: (=> Int) => Boolean = { x => x == 1 && x == 2 }
((m.byNameParam _): (=> Int) => String).expects(new FunctionAdapter1(f)).returning("it works")
var y = 0
assertResult("it works") { m.byNameParam { y += 1; y } }
}
}
}
34 changes: 34 additions & 0 deletions jvm/src/test/scala-3/mock/ByNameParametersTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package mock

import com.paulbutcher.test.TestTrait
import org.scalamock.scalatest.MockFactory
import org.scalatest.funspec.AnyFunSpec
import org.scalatest.matchers.should.Matchers

class ByNameParametersTest extends AnyFunSpec with MockFactory with Matchers {

autoVerify = false

it("cope with methods with by name parameters") {
withExpectations {
val m = mock[TestTrait]
(m.byNameParam(_: Int)).expects(*).returning("it worked")
assertResult("it worked") {
m.byNameParam(42)
}
}
}

it("match methods with by name parameters") {
withExpectations {
val m = mock[TestTrait]
(m.byNameParam(_: Int)).expects(where[Int](Set(1, 2))).returning("it works")
var y = 0
assertResult("it works") {
m.byNameParam {
y += 1; y
}
}
}
}
}
Loading