Test if a method was called without providing parameters - scala

I have the following code:
class MyClass {
def someMethods(): Unit = {
val result1 = method1()
val result2 = method2(result)
}
}
No I want to test if method1 and method2 are called, when I run someMethod.
class TestMyClass {
#Test
def testSomeMethods(): Unit = {
val myClass = new MyClass()
val myClassSpy = Mockito.spy(myClass)
myClassSpy.someMethods()
verify(myClassSpy).method1()
}
}
For method1 this is working, but method2 needs a parameter, that is provided by method1.
Can I not just do something like assertTrue(method2.called)?
Because I do not want to check the result of the methods, I just want to know if they were called.

Hmm, using a spy for that is already a smell, you shouldn't be testing internals of your class like that.
In any case you could do Mockito.verify(myClassSpy).method2(Mockito.any()) and that would do the trick, but I'd seriously review your design and the motivation behind this test as it really feels like the wrong approach.

Related

Mockito-Mock functions within scala object for unit testing

I have a few functions within a scala object. The functions internally call other functions of the same object.
object A {
def method1:Unit= {
spark=CreateSparkSession.create()
Method2(spark,dbnm)
}
def Method2(spark:Sparksession, dbnm:String):Unit= {
//some implementation
}
}
How can I write Unit testcase for Method1 without actually invoking method2.
CreateSparksession is another object with create method that returns sparksession.
You cannot mock methods in an object. And you should not mock methods in class that you are testing (if it looks like you need to, it is a definite symptom of violating the single responsibility principle).
What you can do is something like this:
trait Api1 {
def method1(
...
): Unit // NB: also, should not really return a Unit: how are you going to test this???
}
trait Api2 {
def method2(...): Unit // See above
}
class Impl2 extends Api2 {
def method2(...) = // Do stuff
}
class Impl1(val api2: Api2) extends Api1 {
def method1(...) = { ... ; api2.method2(); ... }
}
// You should not really need this, but, you can have it if you want
object A extends Impl1(new Impl2)
So, now testing this code is trivial:
describe("Impl2") {
it ("does nothing") {
new Impl2().method2("foo")
// Nothing happens
// this is what I meant: how do you know it worked?
}
}
describe("Impl1") {
it ("does nothinig") {
val a2 = mock[Api2]
doNothing when a2 method2(any)
val fixture = new Impl1(a2)
fixture.method1()
// Again, nothing happens!
verify(a2).nothing("foo")
}

Scala mocking trait that is extended by another trait

I am trying to test
trait Name extends Helper {
def name() = {
var s = getSystem()
s.name()
}
}
where all I want to do is make sure that the "s.name()" method is invoked once by mocking an instance of s, which is a System.
Helper is defined as so:
trait Helper {
def getSystem() : System = {
systemGetter.get()
}
}
As of now, my NameSpec looks something like:
class NameSpec extends FlatSpec with Matchers with MockitoSugar {
class NameImpl extends Name
var toTest = new NameImpl
val mockSystem = mock[System]
it should "call s.name() once" in {
when(getSystem() is invoked, return a mockSystem)
toTest.name()
// Verify that mockSystem.name() happened only once
}
}
What I'm confused about is how to return a mock System in toTest.name() when it calls getSystem() so that I can verify that the system calls s.name() only once. I could easily mock this System if it were a parameter to the name() method in Name trait, so I guess I don't know how to "inject" a mockSystem to be used instead of a real system when that method is invoked.
Unfortunately your code is not compilable and thus is obviously an inadequate representation of what you really have. Particularly it is not clear how the Helper really gets an object of type System. I think that in the real code you should mock the systemGetter, that I suppose is somehow injected into the objects implementing Helper trait, to return your mockSystem. However it is hard to show you a valid example of that basing on the code you provided. If for some reason this is not what you can do, there are a few more avenues.
You seem to use something like Cake pattern around Helper and its inheritance. If so, you can use a class instead of NameImpl to inject System:
class NameWithInjectedSystem(val system: System) extends Name {
override def getSystem(): System = system
}
it should "call s.name() once" in {
val mockSystem = mock[System]
val nameToTest = new NameWithInjectedSystem(mockSystem)
val mockName = "Mock name"
when(mockSystem.name()).thenReturn(mockName)
val actual = nameToTest.name()
actual should === (mockName)
verify(mockSystem, times(1)).name()
}
Finally you can mock even nameToTest object itself but this is not the way I'd suggest because it binds test to much more implementation details than you should want:
it should "call s.name() once" in {
val mockSystem = mock[System]
val nameToTest = mock[NameImpl]
when(nameToTest.getSystem()).thenReturn(mockSystem)
when(nameToTest.name()).thenCallRealMethod()
val mockName = "Mock name"
when(mockSystem.name()).thenReturn(mockName)
val actual = nameToTest.name()
actual should ===(mockName)
verify(mockSystem, times(1)).name()
}
Note how you must call thenCallRealMethod for the .name() call and so you should do for all the calls inside the name or the test will not work.

Require user to call a method eventually

Assume I have a class like this:
case class Test(pars: Seq[Int] = Seq()) {
def require(p: Int) = copy(pars = p +: pars)
def execute() = {assert(???)}
}
It is intended to be used like this:
Test().require(1).require(2).execute()
I am using this in tests. Sometimes it happens I forget to call execute() which makes the test to pass, as the testing code is not executed at all.
Would it be possible to create a check to notify me about this? I have tried an implicit conversion to unit, but it was not applied, default compiler one is used:
implicit def toUnit(setup: Test): Unit = setup.execute() // or ???
It is not a big issue, I can solve it by being more careful, but having a compiler (or even runtime) to warn me would make it easier. The actual way to how create or execute the test is not important and can be changed, it does not have to be a case class and its member.
A possible solution might be refactoring to something along these lines:
sealed abstract class Test private (pars: Seq[Int] = Seq()) {
def require(p: Int): Test = new Test.Impl(pars = p +: pars)
private def execute(): Unit = println("Execute!")
}
object Test {
def apply(f: Test => Test) = f(new Test.Impl()).execute()
private class Impl(pars: Seq[Int] = Seq()) extends Test(pars)
}
Test {
_.require(1).require(2)
}
The idea of the solution is to hide the Test constructor, so that the one able to call it can guarantee execute is always paired with it.
You can do it for all (non-Unit) types by using the -Ywarn-value-discard compiler option. If you want to limit it to Test, this should be doable with Wart Remover.
After some experimentation I came with a solution which allows me to write the execute before the test setup instead of after it, this way it is easier for me not to forget:
object execute {
def --(setup: Test) = setup.execute()
}
execute -- Test().require(1)

How store methods vals without recreating them every method call

I have Scala class which methods use a lot of regex. Each class method use some regex patterns.
Looking from the perspective of code modularity I should store those patterns in method:
class Bar {
def foo() {
val patt1 = "[ab]+".r
val patt2 = "[cd]+".r
/*...*/
}
}
But this approach is quite inefficient. Patterns are recompiled on each method call.
I could move them directly to class:
class Bar {
val fooPatt1 = "[ab]+".r
val fooPatt2 = "[cd]+".r
/*...*/
}
but in case when I have 30 methods it looks ugly.
I ended up with some hybrid solution using val and anonymous function:
val z = {
val patt1 = "[ab]+".r
val patt2 = "[cd]+".r
() => { /* ... */ }
}
but I am not sure if using val to store function have some drawbacks compared to def. Maybe there is other clean solution to store methods constants without polluting the class?
Using a val is perfectly fine. There might be a (very) small performance hit, but in most (99.9%) of the applications that's not a problem.
You could also create a class for the method
// The extends is not needed, although you might want to hide the Foo type
class Foo extends (() => ...) {
val patt1 = "[ab]+".r
val patt2 = "[cd]+".r
def apply() = {
...
}
}
Then in the class:
class Bar {
val foo = new Foo
}
Another solution is using traits
trait Foo {
private lazy val patt1 = "[ab]+".r
private lazy val patt2 = "[cd]+".r
def foo() = ...
}
class Bar extends Foo with ...
Note that if you have different methods like that in a single class, it can be sign that the single responsibility principle is violated. Moving them to their own class (or trait) can be a solution for that problem as well.
I would put every method with the necessary regex in it's own Trait:
class Bar extends AMethod with BMethod
trait AMethod {
private val aPattern = """\d+""".r
def aMethod(s: String) = aPattern.findFirstIn(s)
}
trait BMethod {
private val bPattern = """\w+""".r
def bMethod(s: String) = bPattern.findFirstIn(s)
}
clean
separated
easy to test (object AMethodSpec extends Properties("AMethod") with AMethod ...)
I took into account Chris comment. Putting patterns to companion object is probably the most efficient approach but very unclean when we have more methods.
EECOLOR solution is less efficient but cleaner. Traits prevents recreating patterns on each method call. Unfortunately, scala do not use same compiled pattern accross multiple class instances:
(new X).patt1==(new X).patt1 // would be false.
I've combined those two approaches and instead traits I used objects.
object X {
object method1 {
val patt1 = "a".r
}
object method2 {
val patt1 = "a".r
}
}
class X {
def method1 = {
import X.method1._
patt1
}
def method2 = {
import X.method2._
patt1
}
}
(new X).method1 == (new X).method1 // true
(new X).method2 == (new X).method2 // true
Although this approach works, I think scala should provide some solution for that problem out of box. Patterns are the simplest example. We could have other immutable objects which initialization is much more expensive.
Extracting method internals somewhere outside is still unclear. It would be nice to do it like with lazy vals. Adding one modificator should ensure that value is instance only once across all instances and methods calls. It would be something like that:
def method1 {
static val x = new VeryExpensiveObject
}

Mockito for Objects in Scala

I'm using Scala 2.10, specs2 and Mockito. I want to mock scala.io.Source.fromURL(). The issue seems to be fromURL() is a function in io.Source's object.
val m = mock[io.Source]
m.fromURL returns io.Source.fromString("Some random string.")
It's a pretty straightforward mock in an Unit test. Why isn't it working?
Thanks!
Instead of mocking it, you could try spying it as follows:
val m = spy(io.Source)
Or you could mock it as follows:
val m = mock[io.Source.type]
But then how are you using Source in the class you are testing? If you had an example class like so:
class MyClass{
def foo = {
io.Source.doSomething //I know doSomething is not on Source, call not important
}
}
Then in order to take advantage of mocking/spying, you'd have to structure your class like so:
class MyClass{
val source = io.Source
def foo = {
source.doSomething
}
}
And then your test would have to look something like this:
val mockSource = mock[io.Source.type]
val toTest = new MyClass{
override val source = mockSource
}
In the Java world, static methods are the bane of mocking. In the Scala world, calls to objects can also be troublesome to deal with for unit tests. But if you follow the code above, you should be able to properly mock out an object based dependency in your class.
Good news! With the latest 1.16 release of mockito-scala, you can now mock scala objects.
To enable withObjectMocked feature, it is mandatory to create the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line:
mock-maker-inline
Example:
object FooObject {
def simpleMethod: String = "not mocked!"
}
"mock" should {
"stub an object method" in {
FooObject.simpleMethod shouldBe "not mocked!"
withObjectMocked[FooObject.type] {
FooObject.simpleMethod returns "mocked!"
//or
when(FooObject.simpleMethod) thenReturn "mocked!"
FooObject.simpleMethod shouldBe "mocked!"
}
FooObject.simpleMethod shouldBe "not mocked!"
}
}
See: https://github.com/mockito/mockito-scala#mocking-scala-object
Years later, above answer doesn't work as others have pointed out.
And you cannot mock the scala.io.Source object.
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. You may want to try using an adapter or façade in your code to make it testable. It is better to test against a trait/interface instead of a concrete implementation. There are libraries that support this kind of mocking, such as PowerMock. Be aware that this kind of mocking involves Bytecode manipulation, which has the risk that your test double diverges from the actual implementation.
So what I did is an work around to abstract out scala.io.Source.fromUrl() as a function argument and pass in mocked function in tests.
// original func
def aFuncThatUsesSource() = {
val source = scala.io.Source("127.0.0.1:8080/...")
val result = source.mkString
Try(source.close())
result
}
// test friendly func that accepts `scala.io.Source.fromURL` as arg
def aTestFriendlyFunc(makeApiCall: String => BufferedSource) = {
val source = makeApiCall("127.0.0.1:8080/...")
val result = source.mkString
Try(source.close())
result
}
....
// test spec
def testyMcTesterson = () => {
val makeApiCall = mockFunction[String, BufferedSource]
makeApiCall.expects("something...")
.returns( new BufferedSource(new ByteArrayInputStream("returns something".getBytes)) )
aTestFriendlyFunc(makeApiCall) shouldEqual "returns something"
}