ScalaMock
ScalaMock copied to clipboard
Testing scala Parser and get `Parameter type in structural refinement may not refer to an abstract type defined outside that refinement`
If you want to discuss a new feature, please ignore/clear this form.
ScalaMock Version (e.g. 3.5.0)
5.2.0
Scala Version (e.g. 2.12)
2.13
Runtime (JVM or JS)
JVM
Please describe the expected behavior of the issue
Trying to mock a trait with scala Parser. Receive error like follows:
Parameter type in structural refinement may not refer to an abstract type defined outside that refinement val mockedCommandDispatcher = mock[UserRepositoryManagementCommandDispatcher]
Reproducible Test Case
Please provide a minimised code snippet that fails, ideally, written as a failing test case in ScalaTest. This will help us a lot in diagnosing the problem and work on a fix. If the issue is more complex or requires configuration, please provide a link to a project on Github that reproduces the issue.
`
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.scalamock.scalatest.MockFactory
import scala.util.parsing.combinator.RegexParsers
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
trait PareserTrait {
def findUser(username: String): Future[(String, String)]
def parseUser: Parser[Future[String]] = ("find-user" ~> word | ":") ^^ { username =>
findUser(username).map(result => s"${result._1} for username ${result._2}")
}
}
class ParserTraitTest extends AnyFlatSpec with Matchers with MockFactory with ParserTrait with RegexParsers {
"ParserTrait" should "parse user correctly with the expected username" in {
val parserTrait = mock[ParserTrait]
val expectedUsername = "John"
val expectedResult = ("User found", expectedUsername)
(parserTrait.findUser _)
.expects(expectedUsername)
.returning(Future.successful(expectedResult))
val input = s"find-user $expectedUsername"
val result: Future[String] = parse(parserTrait.parseUser, input) match {
case Success(parsedResult, _) => parsedResult
case Failure(msg, _) => Future.failed(new RuntimeException(s"Parsing failed: $msg"))
}
// Now you can assert on the parsed result without worrying about the implementation details.
result.map { parsedValue =>
parsedValue shouldBe s"${expectedResult._1} for username ${expectedResult._2}"
}
}
}