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

Mocking case classes and classes without default constructor #56

Closed
spontagent opened this issue Jan 15, 2014 · 35 comments
Closed

Mocking case classes and classes without default constructor #56

spontagent opened this issue Jan 15, 2014 · 35 comments
Labels
Milestone

Comments

@spontagent
Copy link

How would I mock case classes?

@cb372
Copy link
Collaborator

cb372 commented Jan 15, 2014

Currently ScalaMock can only mock classes with a default constructor. If your case class has a default constructor, you should be able to mock it just like a regular class.

Example:

src/main/scala/Foo.scala

case class Foo(a: Int, b: String) {
  def this() = this(1, "asdf") // default constructor
  def something(): Int = 3
}

src/test/scala/FooTest.scala

import org.scalatest._
import org.scalamock.scalatest.MockFactory

class FooTest extends FlatSpec with Matchers with MockFactory {
  "Case class" should "be mocked" in {
    val foo = mock[Foo]
    (foo.something _).expects().returning(5)
    foo.something() should be(5)
  }
}

@pawel-wiejacha
Copy link
Collaborator

You don't have to modify your production code by adding a default constructor to case classes.

Example. For case class:

case class CaseClass(integer : Int, string : String) {
  def method() : Integer = integer + 100
}

You can workaround this ScalaMock issue by extending given case class in test code and providing some fake/mock arguments, e.g:

class MockableCaseClass extends CaseClass(0, null)
val m = mock[MockableCaseClass]
(m.method _).expects().returning(5)

We can easily extend MockMaker.initDef method to support mocking classes without a default constructor

@pawel-wiejacha pawel-wiejacha changed the title How would I mock case classes? Mocking case classes and classes without default constructor Aug 23, 2014
@gavares
Copy link

gavares commented Mar 4, 2015

This strategy works but requires quite a bit of boilerplate in a project that has a lot of case classes. Being able to mock[MyCaseClass] would be very useful.

@eamonnfaherty-productmadness

👍

@danmbyrd
Copy link

👍 This would be great if we could avoid the boiler plate.

@jeroenvlek
Copy link

👍

@michaelahlers
Copy link

👍

11 similar comments
@tricker
Copy link

tricker commented Sep 2, 2015

👍

@gabadi
Copy link

gabadi commented Sep 17, 2015

+1

@szabba
Copy link

szabba commented Sep 29, 2015

👍

@nolanofra
Copy link

👍

@psttf
Copy link

psttf commented Oct 18, 2015

👍

@fajarmf
Copy link

fajarmf commented Oct 19, 2015

👍

@autodidacticon
Copy link

👍

@eyalroth
Copy link

eyalroth commented Dec 8, 2015

👍

@hensg
Copy link

hensg commented Dec 9, 2015

👍

@gabadi
Copy link

gabadi commented Dec 23, 2015

+1

@nolanofra
Copy link

👍

@lhohan
Copy link

lhohan commented Feb 9, 2016

👍

1 similar comment
@snaik
Copy link

snaik commented Feb 21, 2016

👍

bkowalik added a commit to bkowalik/ScalaMock that referenced this issue Mar 18, 2016
@bkowalik
Copy link

I have made PR. Please make review.

bkowalik added a commit to bkowalik/ScalaMock that referenced this issue Mar 24, 2016
bkowalik added a commit to bkowalik/ScalaMock that referenced this issue Mar 24, 2016
bkowalik added a commit to bkowalik/ScalaMock that referenced this issue Mar 24, 2016
bkowalik added a commit to bkowalik/ScalaMock that referenced this issue Mar 25, 2016
@eviatharbl
Copy link

+1

1 similar comment
@atanana
Copy link

atanana commented Apr 30, 2016

+1

@szymon-rd
Copy link

+1
I'm totally unable to use it with akka testkit because of it.

@JosephSe
Copy link

+1

6 similar comments
@greenhost87
Copy link

+1

@smrnv
Copy link

smrnv commented Jul 29, 2016

+1

@burungbangkai
Copy link

+1

@akhil
Copy link

akhil commented Aug 26, 2016

+1

@xavier-fernandez
Copy link

+1

@supramo
Copy link

supramo commented Sep 22, 2016

+1

ShaneDelmore added a commit to ShaneDelmore/ScalaMock that referenced this issue Nov 10, 2016
paulbutcher#56 Mocking class with nonempty default constructor
barkhorn added a commit that referenced this issue Jan 7, 2017
@barkhorn barkhorn added this to the v3.5.0 milestone Jan 7, 2017
barkhorn added a commit that referenced this issue Jan 7, 2017
@barkhorn
Copy link
Collaborator

barkhorn commented Jan 7, 2017

just merged some code into master to support constructors with parameters, see PR #163

@barkhorn barkhorn closed this as completed Jan 7, 2017
@ddpaimon
Copy link

👍

@bbarker
Copy link

bbarker commented Oct 27, 2017

I still (in 3.6.0) seem to experience an NPE on mocking a class TableLactationCurves that looks like the following:

class TableLactationCurves(stream: InputStream) extends DataSetXml(stream) with LactationCurves {

The problem is in the DataSetXml constructor:

class DataSetXml(stream: InputStream) {
  protected var dataTypes: mutable.Map[String, DataType] = mutable.Map()
  protected var data: Array[Array[Any]] = null
  private var description: String = null

  try {
    val is = new InputSource()
    is.setCharacterStream(new StringReader(Utils.readStringFromInputStream(stream)))
    loadData(null, is)
  } catch {
    case ex: Exception =>
      throw new RuntimeException(ex)
  }

Of course, i could fix this by not throwing a RuntimeException, I suppose, but that would change application behavior.

Update: As a workaround, I changed this horrid Java-esque (largely translated by IntelliJ) code to have constructors that have lazy val members - this solved the initialization issue for me, though I still think supporting non-lazy initialization makes sense for some cases.

@barkhorn
Copy link
Collaborator

Your constructor works on the stream parameter, so NPEs will be expected.
In macro mocks, the constructor actions will be executed.
This might be undesirable, but we can not change this behaviour.
As an alternative, you can try using Proxy Mocks - org.scalamock.scalatest.proxy.MockFactory or org.scalamock.scalatest.MixedMockFactory can create these.
You could also subclass DataSetXml and hardwie the stream parameter to point at a mock/stub.

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

No branches or pull requests