Scala Mock partial stubbing
Asked Answered
R

3

12

I'd like to stub one of the methods of a scala class with dependencies. Is there a way to achieve this using ScalaMock?

Here is a simplified example of what I have:

class TeamService(val dep1: D1) {

  def method1(param: Int) = param * dep1.magicNumber()

  def method2(param: Int) = {
    method1(param) * 2
  }
}

In this example I'd like to mock method1(). My test would look like:

val teamService = ??? // creates a stub
(teamService.method1 _).when(33).returns(22)
teamService.method2(33).should be(44)

Is there a way to achieve this?

Rebuttal answered 26/1, 2016 at 14:50 Comment(3)
I think that if you are mocking some class, you don't want to depend on its implementation, but now you seem to be trying to depend on implementation of method1 and on D1. Maybe there is not enough information but you maybe should mock all methods you need to use.Tavey
looks like scala mock doesn't support this feature :(Rebuttal
I belive there is an issue asking for this feature here : github.com/paulbutcher/ScalaMock/issues/141Plethoric
D
1

As suggested in other questions, here and here, we can combine stub with final. From ScalaMock FAQ:

Can I mock final / private methods or classes?

This is not supported, as mocks generated with macros are implemented as subclasses of the type to mock. So private and final methods cannot be overridden

So you can either declare method2 in your source code as final, and then test:

it should "test" in {
  val teamService = stub[TeamService]
  (teamService.method1 _).when(33).returns(22)
  teamService.method2(33) shouldBe 44
}

Or, create a new overriding class that declares your method as final:

it should "test" in {
  class PartFinalTeamService(dep: D1) extends TeamService(dep) {
    override final def method2(param: Int): Int = super.method2(param)
  }

  val teamService = stub[PartFinalTeamService]
  (teamService.method1 _).when(33).returns(22)
  teamService.method2(33) shouldBe 44
}
Delldella answered 5/11, 2020 at 13:42 Comment(0)
M
0

You must mock dep1: D1, so everything gonna works well. It's not a good approach to mock "half" or only some methods.

Mocking dep1: D1 is the right way to test it.

val mockD1 = mock[D1]
val teamService = new TeamService(mockD1)
(mockD1.magicNumber _).returns(22)
teamService.method2(33).should be(44)
Malacostracan answered 19/9, 2017 at 14:3 Comment(0)
B
0

You can override method1() while creating the TeamService object and make it return whatever value you want.

val service = new TeamService(2) {
  override def method1(param: Int): Int = theValueYouWant
}

And use the service object to test your method2().

Brace answered 16/7, 2021 at 5:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.