Search code examples
scalasbtcucumbercucumber-junitscalamock

Using scalamock outside of MockFactory


I want to add integration tests to my project using cucumber feature files. I have got this working using this project as an example: https://github.com/jecklgamis/cucumber-jvm-scala-example

The problem I am running into is when I want to mock some objects. ScalaMock and EasyMock all seem to need scalatest or something similar.

My build.sbt has these lines:

    libraryDependencies ++= Seq(
  "io.cucumber" %% "cucumber-scala" % "2.0.1" % Test,
  "io.cucumber" % "cucumber-junit" % "2.0.1" % Test,
  "org.scalamock" %% "scalamock" % "4.0.0" % Test,
  "org.scalatest" %% "scalatest" % "3.0.1" % Test,
  etc..

My stepdef file has this:

import com.typesafe.config.{Config, ConfigFactory}
import cucumber.api.scala.{EN, ScalaDsl}
import eu.xeli.jpigpio.JPigpio

class StepDefs extends ScalaDsl with EN {
  var config: Config = null
  var jpigpio: JPigpio = null

  Given("""^an instance of pigpio$""") { () =>
    jpigpio = mock[JPigpio]
  }
}

The mock[JPigpio] call gives a symbol not found error. I assume because this class does not extend MockFactory.

How can I use scalamock outside of an MockFactory class?


Solution

  • Bit of a quick and dirty example that does not pull in Scalatest, but I'm sure you can piece the rest together. I'd actually be curious to see this working with Cucumber :)

    import org.scalamock.MockFactoryBase
    import org.scalamock.clazz.Mock
    
    object NoScalaTestExample extends Mock {
      trait Cat {
        def meow(): Unit
        def isHungry: Boolean
      }
    
      class MyMockFactoryBase extends MockFactoryBase {
        override type ExpectationException = Exception
        override protected def newExpectationException(message: String, methodName: Option[Symbol]): Exception =
          throw new Exception(s"$message, $methodName")
    
        def verifyAll(): Unit = withExpectations(() => ())
      }
    
      implicit var mc: MyMockFactoryBase = _
      var cat: Cat = _
    
      def main(args: Array[String]): Unit = {
        // given: I have a mock context
        mc = new MyMockFactoryBase
        // and am mocking a cat
        cat = mc.mock[Cat]
        // and the cat meows
        cat.meow _ expects() once()
        // and the cat is always hungry
        cat.isHungry _ expects() returning true anyNumberOfTimes()
    
        // then the cat needs feeding
        assert(cat.isHungry)
    
        // and the mock verifies
        mc.verifyAll()
      }
    }
    

    This will actually throw as the meows expectation is not satisfied (just to demo)

    Exception in thread "main" java.lang.Exception: Unsatisfied expectation:
    
    Expected:
    inAnyOrder {
      <mock-1> Cat.meow() once (never called - UNSATISFIED)
      <mock-1> Cat.isHungry() any number of times (called once)
    }
    
    Actual:
      <mock-1> Cat.isHungry(), None
        at NoScalaTestExample$MyMockFactoryBase.newExpectationException(NoScalaTestExample.scala:13)
        at NoScalaTestExample$MyMockFactoryBase.newExpectationException(NoScalaTestExample.scala:10)
        at org.scalamock.context.MockContext$class.reportUnsatisfiedExpectation(MockContext.scala:45)
        at NoScalaTestExample$MyMockFactoryBase.reportUnsatisfiedExpectation(NoScalaTestExample.scala:10)