Skip to content

With Scala 2.13 mockito-scala always treats ArraySeq[_] in last argument position as varags list #352

@seigert

Description

@seigert

It could be reproduced with following Ammonite script:

import $ivy.{
  `org.mockito::mockito-scala-scalatest:1.16.15`,
  `org.scalatest::scalatest:3.2.3`,
  `org.scalatestplus::scalacheck-1-15:3.2.3.0`
}

import org.mockito.captor.{ ArgCaptor, Captor }
import org.mockito.scalatest.MockitoSugar
import org.scalatest.funspec.AnyFunSpec
import org.scalatest.matchers.should.Matchers

import scala.collection.immutable.ArraySeq

trait ArraySeqService {
  def testMethod(str: String, args: ArraySeq[String]): IndexedSeq[String]
}
trait IndexedSeqService {
  def testMethod(str: String, args: IndexedSeq[String]): IndexedSeq[String]
}

class MockitoSpec extends AnyFunSpec with Matchers with MockitoSugar {
  val arraySeq = mock[ArraySeqService]
  val indexedSeq = mock[IndexedSeqService]
  when {
    arraySeq.testMethod(any[String], any[ArraySeq[String]])
  }.thenAnswer[String, ArraySeq[String]] { (fst, rst) =>
    fst +: rst
  }
  when {
    indexedSeq.testMethod(any[String], any[IndexedSeq[String]])
  }.thenAnswer[String, IndexedSeq[String]] { (fst, rst) =>
    fst +: rst
  }
  describe("Mockito") {
    it("should allow ArraySeq as a last parameter") {
      arraySeq.testMethod("a", ArraySeq("b", "c")).should(contain).allOf("a", "b", "c")
    }
    it("should allow Vector as a last parameter to IndexedSeq method") {
      indexedSeq.testMethod("a", Vector("b", "c")).should(contain).allOf("a", "b", "c")
    }
    it("should allow ArraySeq as a last parameter to IndexedSeq method") {
      indexedSeq.testMethod("a", ArraySeq("b", "c")).should(contain).allOf("a", "b", "c")
    }
  }
}

(new MockitoSpec).execute()

What's worse, not only last parameters declared as ArraySeq is treated as part of vararg, but also when ArraySeq value passed to a parameter of 'plain' IndexedSeq type, it is also treated as a varargs list.

We think that code of org.mockito.internal.handler.unwrapVarags is a culprit here and some more sophisticated check should be perfomed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions