Mockito-Mock functions within scala object for unit testing - scala

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")
}

Related

Dependency injection without classes Scala

I like to write Scala code without classes, using just functions and objects.
e.g.
object Something {
def foo() = {
SomeDependency().doIt()
...
}
}
object SomethingElse {
def baz = {
val x = Something.foo()
...
}
}
However, I run into the issue that I can't test that code, since I can't mock anything out. I'd have to refactor the code and make it take a parameter and then have to needlessly instantiate classes.
class Something(someDependency: SomeDependency) {
def foo() = {
someDependency.doIt()
...
}
}
class SomethingElse(something: Something) {
def baz = {
val s = new SomeDependency()
val x = new Something(s).foo()
...
}
}
What I sometimes do is use implicits but it gets cumbersome since you need to add it to every method.
object Something {
def foo()(implicit someDependency: SomeDependency) = {
someDependency().doIt()
...
}
}
object SomethingElse {
def baz(implicit something: Something) = {
val x = something.foo()
...
}
}
In other languages like Python/JS, you can just mock the dependency directly, instead of making your class take in dependencies. Is there any way to solve this, or is just an antipattern to write scala without classes.
Despite being able to work imperatively in Scala, Scala is designed for Functional Programming. The fact that you need to mock things means that your functions have side effects, therefore, they are not pure functions so it isn't functional programming.
There are mock frameworks in Scala but they don't allow you to overwrite the functionality of your functions like you can do with Python, for example.
You could use also high order functions to pass dependencies, something like this:
object Something {
def foo(someDependencyFunction: A => B): C = {
someDependencyFunction(...)
...
}
}
object SomethingElse {
def bar(SomethingFoo: (A => B) => C)(someDependencyFunction: A => B): D = {
SomethingFoo(someDependencyFunction)
...
}
}
But I don't really see the point of avoiding classes, maybe if you explain why you don't want to use classes someone can help better on a solution

Scala: reconfigure trait using CLI parameters

I have a Scala application, where pretty much every object extends a specific trait, which holds all the main functions and variables used by pretty much the entire system.
I want to add a --testing flag to my app's command line variables, which will shift the the results of some of the functions in the trait.
Putting it simply, I'd like the variable accepted in the main to have an affect that alters something in the trait before it is extended by the objects - without sending it explicitly to all objects.
Any ideas how that can be performed?
I doubt you really want to dynamically modify a trait, and I am not sure if it possible that all your classes inheriting that trait would be affected. I don't know enough about the compiler and byte code.
A way to accomplish something similar would be to have your trait take a parameter, and make your trait act conditionally on the parameter.
trait Foo {
val testing: Boolean
def fn1(): Unit = {
if (testing) {
println("testing")
} else {
println("production")
}
}
}
class Bar(val testing: Boolean) extends Foo {
def fn2(): Unit = {
fn1()
}
}
new Bar(true).fn2()
new Bar(false).fn2()
Your question is broad and this is just my 5 cents.
Update
trait Foo {
def fn1(): Unit = {
if (Foo.testing) {
println("testing")
} else {
println("production")
}
}
}
object Foo {
var testing: Boolean = false
}
class Bar extends Foo {
def fn2(): Unit = {
fn1()
}
}
object SOApp extends App {
new Bar().fn2()
Foo.testing = true
new Bar().fn2()
}
Consider passing the 'testing' flag to the trait's initializer block like this:
trait MyTrait {
var testMode: Boolean = _
def doSomething(): Unit = {
if (testMode)
println("In Test Mode")
else
println("In Standard Mode")
}
}
// IMPORTANT: Your best bet would be to create some Config object
// that is loaded and initialized in a main method.
// Define test-specific Config class:
case class Config(testMode: Boolean) {
def isTestMode: Boolean = this.testMode
}
// Instantiate in main method:
val config = new Config(true)
// Later, extend the trait:
class MyObj extends MyTrait { testMode = config.isTestMode() }
// Then just invoke
new MyObject().doSomething()

Is it possible to mock a function that is defined within another function?

I have some functions that access a database, which I need to mock for testing purposes.
For ease of use, I would like to define these functions within another function, where I can leverage scope to reduce the number of arguments I have to pass.
I need to test the parent function, while mocking the nested functions.
Are there any tricks to mock functions that are nested?
As a secondary question, are there ways to mock functions when nested at arbitrary depth?
And a side note: my project is light enough I'm not even using classical mocking, just stackable traits like this blog post suggests; but for this question, any kind of mocking is fine.
Here is some very simple example code:
class Storage {
def storeData(specId: Long, data: String): Unit = {
val rawPath = "/path/to/file"
def storeFsEntry: Unit = {
// do stuff
}
def storeDbEntry: Unit = {
// do stuff we need mocked
}
if ( specId == 1 )
{
storeDbEntry
storeFsEntry
}
}
}
It's not possible, but you can define a trait and implement it inside your function (if you really want this logic been implemented inside):
class Storage {
trait Storing {
def path: String //you have to define all free members
def storeDbEntry: Unit
def storeFsEntry: Unit
}
def storeData(specId: Long, data: String, storingDefault: Option[Storing] = None): Unit = {
val myStoring = new Storing {
...implement it here
}
val storing = storingDefault getOrElse myStoring
import storing._
if ( specId == 1 ) {
storeDbEntry
storeFsEntry
}
}
}
Your mock will be something like that:
trait StorageMock extends Storage {
override def storeData(specId: Long, data: String, storingDefault: Option[Storing] = None): Unit = {
val storingOverride = new Storing { ... } //mocking functionality
super.storeData(specId, data, storingDefault orElse Some(storingOverride))
}
}
new Storage with StorageMock
You may also turn storingDefault into a member instead of function parameter.
The reason why it's not possible to do same for inner functions is that they are private and also typecheck can't be performed on them (in comparison with inner traits).

DRY up boilerplate in object/class default constructor

I have something like this:
abstract class RunnerBase { def printErrorAndBreak = ... }
object Runner1 extends RunnerBase {
breakable {
doSomething
if (cond1) printErrorAndBreak(...)
}
}
object Runner2 extends RunnerBase {
breakable {
if (cond1) printErrorAndBreak(...)
something else
}
}
I'd like to move the breakable { ... } part into RunnerBase so that Runner1 and Runner2 looked like this instead:
object Runner1 extends RunnerBase {
doSomething
if (cond1) printErrorAndBreak(...)
}
object Runner2 extends RunnerBase {
if (cond1) printErrorAndBreak(...)
something else
}
Is this even possible? Or is my only way to wrap the subobject logic in, say, a run method?
UPDATE: Based on the accepted answer (and regardless of the comments), for the sake of robustness and simplicity, I've decided to go with this:
class RunnerBase { def run = breakable _ }
class Runner1 { run { doSmth; if (?) printErrorAndBreak } }
class Runner2 { run { doSmth; if (?) printErrorAndBreak } }
Not perfect because there's still the run { ... } repetition, but at least breakable and break are encapsulated in RunnerBase.
How about DelayedInit?
import scala.util.control.Breaks._
trait BreakInit extends DelayedInit {
def delayedInit(body: => Unit) {
breakable {body}
}
}
class MyClass extends BreakInit {
println("Hello World")
break()
println("Error - should not be reachable")
}
val a = new MyClass
In this case, we've created a trait BreakInit that inherits from DelayedInit, which overrides the delayedInit method to call the constructor within a breakable block. MyClass's constructor is then rolled up into a function, and passed to the delayedInit method. As #som-snytt points out, the DelayedInit magic only affects class constructors, not trait constructors.
However, I'd advise a note of caution when using DelayedInit. It involves some reasonably deep compiler magic, and magic always comes with a price. Personally, I'd tend to prefer your original approach, as there's less magic involved.

Inject a dependency inside an object

I'm new to the Play framework and scala and I'm trying to inject a dependency inside a companion object.
I have a simple case class, like:
case class Bar(foo: Int) {}
With a companion object like:
object Bar {
val myDependency =
if (isTest) {
// Mock
}
else
{
// Actual implementation
}
val form = Form(mapping(
"foo" -> number(0, 100).verifying(foo => myDependency.validate(foo)),
)(Bar.apply)(Bar.unapply))
}
This works fine, but it's not really a clean way to do it. I'd like to be able to inject the dependency at build time so that I can inject different mock objects when testing and different real implementations in development and production.
What's the best way to achieve this?
Any help really appreciated. Thanks!
Along the lines of the Cake, we can try to change your example to
trait Validator {
def validate(foo: Int): Boolean
}
trait TestValidation {
val validator = new Validator {
def validate(foo: Int): Boolean = ...
}
}
trait ImplValidation {
val validator = new Validator {
def validate(foo: Int): Boolean = ...
}
}
trait BarBehavior {
def validator: Validator
val form = Form(mapping(...))(Bar.apply)(Bar.unapply)
}
//use this in your tests
object TestBar extends BarBehavior with TestValidation
//use this in production
object ImplBar extends BarBehavior with ImplValidation
You should additionally try and test if this example fits well within the Play Framework, too