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

only cast null constructor args for primitives #520

Merged
merged 7 commits into from
Jul 29, 2024

Conversation

martijnhoekstra
Copy link
Contributor

before, we tried to cast applied types to the type arguments, to capture context bounds. That fails for simple generic types that then get cast to the wrong type. However, that's all unnessecary: the only nulls we need to cast are primitives, which can't be passed as null. Anyting else doesn't need a cast at all

Pull Request Checklist

  • I agree to licence my contributions under the MIT licence
  • I have added copyright headers to new files
  • I have added tests for any changed functionality

Fixes

Fixes #519

Purpose

Fix mocking classes with generic parameters. Before, mocking class Foo(x: Option[Int]) failed

Background Context

simplifying the casts by only doing them when needed simplifies thing significantly

References

@goshacodes
Copy link
Collaborator

Hi, thank you for your contribution!

Could you please add more test cases before we merge it?

  1. Test-case from your PR description
class WithOption(opt: Option[Int])
class WithInt(int: Int)
class WithInt(int: String)
class WithC[C[_]](foo: C[Int])
  1. This one is probably already exists
class WithC[A](foo: A)

@barkhorn barkhorn added this to the v6.1.0 milestone Jun 2, 2024
@martijnhoekstra
Copy link
Contributor Author

martijnhoekstra commented Jun 6, 2024

Edit: The following now works:

  class WithOption(opt: Option[String])
  class WithInt(i: Int)
  class WithString(str: String)
  class WithTC[TC[_]](foo: TC[Int])
  class WithGeneric[T](t: T)
  mock[WithOption[]
  mock[WithTC[List]]
  mock[WithGeneric[Int]]
  mock[WithGeneric[String]]

The last thing left that doesn't compile but should is

  type ID[A] = A
  mock[WithTC[ID]]

This is a progression from scalamock 5, where most of this didn't work.

Original message below:

The good:

The following are fine in this MR:

  class WithOption(opt: Option[String])
  class WithInt(i: Int)
  class WithString(str: String)

The bad: none of the following compiles:

  class WithTC[TC[_]](foo: TC[Int])
  class WithGeneric[T](t: T)
  type ID[A] = A
  mock[WithTC[List]]
  mock[WithTC[ID]]
  mock[WithGeneric[Int]]
  mock[WithGeneric[String]]

the good worse: they also don't compile without this MR.

[error] -- [E007] Type Mismatch Error: /Users/martijn.hoekstra/code/ScalaMock/jvm/src/test/scala/com.paulbutcher.test/mock/MockTestJvm.scala:52:21 
[error] 52 |        val tclist = mock[WithTC[List]]
[error]    |                     ^^^^^^^^^^^^^^^^^^
[error]    |                     Found:    TC[List]
[error]    |                     Required: List[Int]
[error]    |
[error]    | longer explanation available when compiling with `-explain`
[error] -- [E007] Type Mismatch Error: /Users/martijn.hoekstra/code/ScalaMock/jvm/src/test/scala/com.paulbutcher.test/mock/MockTestJvm.scala:53:19 
[error] 53 |        val tcid = mock[WithTC[ID]]
[error]    |                   ^^^^^^^^^^^^^^^^
[error]    |                   Found:    TC[ID]
[error]    |                   Required: ID[Int]
[error]    |
[error]    | longer explanation available when compiling with `-explain`
[error] -- [E007] Type Mismatch Error: /Users/martijn.hoekstra/code/ScalaMock/jvm/src/test/scala/com.paulbutcher.test/mock/MockTestJvm.scala:54:21 
[error] 54 |        val genInt = mock[WithGeneric[Int]]
[error]    |                     ^^^^^^^^^^^^^^^^^^^^^^
[error]    |                     Found:    T
[error]    |                     Required: Int
[error]    |
[error]    | longer explanation available when compiling with `-explain`
[error] -- [E007] Type Mismatch Error: /Users/martijn.hoekstra/code/ScalaMock/jvm/src/test/scala/com.paulbutcher.test/mock/MockTestJvm.scala:55:24 
[error] 55 |        val genString = mock[WithGeneric[String]]
[error]    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^
[error]    |    Found:    T
[error]    |    Required: String

I expected/hoped that #517 would fix that, which I merged in.

How would you like to move forward? I can make sure there is a clean history on rebase, and mark the failing cases with ignored tests. Would that allow us to move forward with this?

@martijnhoekstra martijnhoekstra force-pushed the fix-constructor-params branch from dabe3b1 to 555ab0c Compare June 6, 2024 11:29
before, we tried to cast applied types to the type arguments, to capture context bounds. That fails for simple generic types
that then get cast to the wrong type. However, that's all unnessecary: the only nulls we need to cast are primitives, which can't
be passed as null. Anyting else doesn't need a cast at all
@martijnhoekstra martijnhoekstra force-pushed the fix-constructor-params branch from 9f20f92 to b2cf100 Compare June 6, 2024 11:33
@martijnhoekstra martijnhoekstra force-pushed the fix-constructor-params branch from b2cf100 to cf3ab78 Compare June 6, 2024 15:18
@segery
Copy link

segery commented Jun 7, 2024

Will the following example work?

import cats.effect.Async

class A[F[_]: Async](val b: B[F])
class B[F[_]: Async](val c: C[F])
trait C[F]

Now I'm getting an error like this.

[error]  type mismatch;
[error]  found   : aa.bb.B[F]
[error]  required: aa.bb.B[cats.effect.IO]
[error]   private val handler = mock[A[IO]]

UPD: For scala 2.13

@martijnhoekstra
Copy link
Contributor Author

martijnhoekstra commented Jun 7, 2024

I'm trying to fix that too @segery -- things seem a bit bumpy at the moment

Edit: yes, that's fixed in this MR, but only for scala 3.

@martijnhoekstra
Copy link
Contributor Author

martijnhoekstra commented Jun 7, 2024

Some of the new tests that pass for scala 3, fail for scala 2.12 and 2.13.

To my surprise, that doesn't seem new: scalamock 5.2.0 shows the same problem: https://scastie.scala-lang.org/aTyLV1LpQ0WEfRJU6s2x5Q

Therefore I moved the tests to a scala 3 specific suite.

That, as far as I'm concerned, makes this MR ready for review again.

@goshacodes
Copy link
Collaborator

Looks good. @barkhorn, merge it pls

@barkhorn barkhorn merged commit 2f7b22c into ScalaMock:master Jul 29, 2024
3 checks passed
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

Successfully merging this pull request may close these issues.

Mocking classes with constructor params with applied types fails
4 participants