Gen.sequence ignores size of given Traversable - scala

Gen.sequence seems to be ignoring size of given Traversable. Is that by design? I'm using version 1.14.0 with Scala 2.13. Following generator
Gen.sequence[List[Int], Int](List.fill(3)(Gen.const(5)))
sometimes generates List of size 1. What am I missing ?
Sample test
import org.scalacheck.Gen
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.{Assertions, FlatSpec, Inside, Inspectors, Matchers, OptionValues}
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
class RuleSpec extends FlatSpec with Matchers with Assertions with OptionValues with Inside with Inspectors with ScalaFutures with ScalaCheckPropertyChecks {
val filterGen = Gen.listOfN(3, Gen.const(5))
val inputGen = Gen.pick(10, 5 to 15).map(_.toList).filter(_.nonEmpty)
"A HasAny rule with partially matching filter" should "validate input" in {
forAll(filterGen, inputGen) { case (filter, input) =>
val result = HasAny(filter: _*).valid(input)
println(s"$result: $filter ${input}\n")
result should be(true)
}
}
}

This might be due to Test Case Minimisation
One interesting feature of ScalaCheck is that if it finds an argument
that falsifies a property, it tries to minimise that argument before
it is reported. This is done automatically when you use the
Prop.property and Prop.forAll methods to create properties, but not if
you use Prop.forAllNoShrink.
Hence try using Prop.forAllNoShrink like so
Prop.forAllNoShrink(filterGen, inputGen) { case (filter, input) => ...
If using ScalaTest's forAll then try the suggestion in Add support for not shrinking values in GeneratorDrivenPropertyChecks #584 by creating the following trait
trait NoShrink {
implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty)
}
and mix it in the spec like so
class RuleSpec extends FlatSpec ... with ScalaCheckPropertyChecks with NoShrink {
...
forAll(filterGen, inputGen) { case (filter, input) => ...

Related

scalatest assert that either is right results in symbol literal is deprecated warning [duplicate]

In scalatest, you’re supposed to be able to test boolean properties using symbols like this:
iter shouldBe 'traversableAgain
But this notation have been deprecated in the most recent versions of scala, so now you’re supposed to write:
iter shouldBe Symbol("traversableAgain")
Which is a bit ugly. Is there any better alternative?
Consider BePropertyMatcher which provides type-safe predicate matching syntax
iter should be (traversableAgain)
for example
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.{BePropertyMatchResult, BePropertyMatcher}
import org.scalatest.matchers.should.Matchers
trait CustomMatchers {
val traversableAgain = new BePropertyMatcher[Iterator[_]] {
def apply(left: Iterator[_]): BePropertyMatchResult =
BePropertyMatchResult(left.isTraversableAgain, "isTraversableAgain")
}
}
class BePropertyMatcherExampleSpec extends AnyFlatSpec with Matchers with CustomMatchers {
"BePropertyMatcher" should "provide type-safe checking of predicates" in {
Iterator(42, 11) should be (traversableAgain)
}
}
There is also a related issue Replacement for using symbols as property matchers for 2.13+ #1679

What to use instead of symbols in scalatest?

In scalatest, you’re supposed to be able to test boolean properties using symbols like this:
iter shouldBe 'traversableAgain
But this notation have been deprecated in the most recent versions of scala, so now you’re supposed to write:
iter shouldBe Symbol("traversableAgain")
Which is a bit ugly. Is there any better alternative?
Consider BePropertyMatcher which provides type-safe predicate matching syntax
iter should be (traversableAgain)
for example
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.{BePropertyMatchResult, BePropertyMatcher}
import org.scalatest.matchers.should.Matchers
trait CustomMatchers {
val traversableAgain = new BePropertyMatcher[Iterator[_]] {
def apply(left: Iterator[_]): BePropertyMatchResult =
BePropertyMatchResult(left.isTraversableAgain, "isTraversableAgain")
}
}
class BePropertyMatcherExampleSpec extends AnyFlatSpec with Matchers with CustomMatchers {
"BePropertyMatcher" should "provide type-safe checking of predicates" in {
Iterator(42, 11) should be (traversableAgain)
}
}
There is also a related issue Replacement for using symbols as property matchers for 2.13+ #1679

Why does Mockito verifyNoMoreInteractions has problem with Scala default values

For a mocked class I have a method for which I would like to test whether there are no more interactions then needed, which looks similar to:
def someMethod(someMandatoryParam: Int, canBeDefaultIds: Option[Ids] = None): Future[Failures] = {...}
when I am mocking to invoke this method without the default parameter and I verify it that way:
verify(someClass).someMethod(someInt)
and then check if there was no more interactions:
verifyNoMoreInteractions(someClass)
I am getting an error that here was some unexpected interactions.
But when in implementation I change this method to use None instead of default value and verify:
verify(someClass).someMethod(someInt, None)
verifyNoMoreInteractions(someClass)
It works correctly.
Is there a problem with Mocikto and default values in Scala?
Default arguments is Scala specific feature which Java Mockito is likely not aware of. Consider how Scala code looks after -Xprint:jvm phase
abstract trait SomeClass extends Object {
def someInt(a: Option): Option = a;
<synthetic> def someInt$default$1(): Option = scala.None;
}
Notice how the default argument became just another method someInt$default$1. Try using mockito-scala which is designed with Scala in mind, for example the following test passes
import org.mockito.{ArgumentMatchersSugar, IdiomaticMockito}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
trait SomeClass {
def someInt(a: Option[Int] = None) = a
}
class MockitoScalaDefaultArgsSpec extends AnyFlatSpec with Matchers with IdiomaticMockito with ArgumentMatchersSugar {
"mockito-scala" should "handle default arguments" in {
val someClass = mock[SomeClass]
someClass.someInt()
someClass.someInt() was called
someClass wasNever calledAgain
}
}

How can I define `LoneElement` and `Emptiness` for composed collections?

I have a case class which is a simple wrapper around a collection:
final case class Foo(foos: Seq[Int])
and in my tests, I'd like to make assertions about the emptiness and lone elements of Foo#foos. I'm currently circumventing the problem by accessing Foo#foos directly:
foo.foos shouldBe empty
or
foo.foos.loneElement should===(1)
This works, but breaks encapsulation.
I've looked through the scalatest docs, but haven't found a way to define these operators outside of a companion.
How can I define them? Bonus points for inlining them in the tests.
Define some implicits to deal with Foo (in the test-directory, not in the main source code tree):
import org.scalatest.enablers.Emptiness
trait FooImplicits {
case class FooLoneElementWrapper(wrapped: Foo) {
def loneElement: Int = {
assert(wrapped.foos.size == 1)
wrapped.foos(0)
}
}
implicit def fooCanHazLoneElement(foo: Foo) = FooLoneElementWrapper(foo)
implicit object FooEmptiness extends Emptiness[Foo] {
def isEmpty(foo: Foo) = foo.foos.isEmpty
}
}
Now simply mixin the trait FooImplicits into the FlatSpec where you would like to use it:
import org.scalatest._
class FooSpec extends FlatSpec with Matchers with FooImplicits {
"Foo" should "be empty when it's empty" in {
Foo(Seq()) shouldBe empty
}
it should "have loneElements" in {
val x = Foo(Seq(1))
x.loneElement should equal (1)
}
}
Profit:
[info] Foo
[info] - should be empty when it's empty
[info] - should have loneElements
Notice that the FooImplicits can be defined in the same package as Foo in the main tree, even though it is in a completely different test-source-code tree. This way, it can access package-visible members of Foo.

How to mock a method with functional arguments in Scala?

I'm trying to mock a method call that takes a call-by-name argument:
import org.scalatest.WordSpec
import org.scalatest.mock.MockitoSugar
import org.mockito.Mockito._
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
trait Collaborator {
def doSomething(t: => Thing)
}
trait Thing
#RunWith(classOf[JUnitRunner])
class Test extends WordSpec with MockitoSugar {
"The subject under test" should {
"call the collaborator" in {
// setup
val m = mock[Collaborator]
val t = mock[Thing]
// test code: this would actually be invoked by the SUT
m.doSomething(t)
// verify the call
verify(m).doSomething(t)
}
}
}
I'm primarily interested in Mockito since that's what I'm using, but I'd be interested to see whether any of the major mock frameworks is capable of this kind of testing. The Test fails at runtime on the verify line, with an error like
Argument(s) are different! Wanted:
collaborator.doSomething(
($anonfun$apply$3) <function>
);
-> at Test$$anonfun$1$$anonfun$apply$1.apply(Test.scala:27)
Actual invocation has different arguments:
collaborator.doSomething(
($anonfun$apply$2) <function>
);
-> at Test$$anonfun$1$$anonfun$apply$1.apply(Test.scala:24)
If I'm understanding the situation correctly, the compiler is implicitly wrapping t in a nullary function that returns t. The mock framework is then comparing that function to the one produced in the test code, which is equivalent but not equals().
My case is a relatively simple version of the problem, but I think this would be an issue with any higher-order function.
This looks ugly, but hopefully it can help you to find good solution:
import org.scalatest.mock.MockitoSugar
import org.mockito.Mockito._
trait Collaborator {
def doSomething(t: => Thing)
}
trait Thing
new MockitoSugar {
// setup
val m = mock[Collaborator]
val t = mock[Thing]
m.doSomething(t)
classOf[Collaborator].getMethod("doSomething", classOf[Function0[_]]).invoke(
verify(m),
new Function0[Thing] {
def apply() = null
override def equals(o: Any): Boolean = t == o.asInstanceOf[Function0[Thing]].apply()
})
}
You can try specs2. In specs2, we "hijack" the Mockito Invocation class to account for byname parameters:
trait ByName { def call(i: =>Int) = i }
val byname = mock[ByName]
byname.call(10)
there was one(byname).call(10)
This problem seems to be specific to by-name invocations because in regular higher order functions you can match against the explicit FunctionX object:
verify(collaborator).somethingElse(any(Function2[String, Thing]))
in the by-name case the wrapping of the argument into a Function0 is done implicitly, and Alexey's answer shows how to invoke the mock with an explicit parameter.
You could write something akin to your own verify which would apply arguments captured by mockito.
Mockito internally records invocation and their arguments with e.g.:
http://code.google.com/p/mockito/source/browse/trunk/src/org/mockito/internal/matchers/CapturingMatcher.java