I'm trying to write a unit test for object A, which uses some methods from another object B. How do I override B's methods?
A.scala
import somePackage.B
object A { // This is to be tested
def fun1(str: String) = {
val str2 = processStr(str) //Say str2 = "sahil"
B.doSomething(str2) // This is to be overridden
}
B.scala
object B {
private def doSomething(str: String) = {
// do something
"abc"
}
}
ATest.scala
class ATest extends FlatSpec {
it "should return sahil instead of abc" in {
// Do something to override B.doSomething
A.fun1("someString")
}
}
This is a design failure at architectural level and a typical XY problem. You should not use singleton without a (really) compelling reason.
Instead for both testability and modularity, consider injecting your dependency explicitly (right now you are declaring the dependency between A and B implicitly through singleton).
class A(b: B) {
def fun1(str: String) = b.doSomething(str)
}
class B {
def doSomething(str: String) = "abc"
}
class ATest extends FlatSpec {
it "" in {
val b = new B { override def doSomething(str: String) = "testing..." }
val a = new A(b)
a.fun1("someString") must beEqual "testing..."
}
}
There is no easy way to do this. Without using DI the only thing that comes to my mind is to overload fun1 with package-private modifier:
package somePackage
import somePackage.B
object A {
def fun1(str: String) = fun1(B.doSomething)
private[somePackage] def fun1(str: String, f: (String) => String) = {
val str2 = processStr(str)
f(str2)
}
}
Then you can pass any mock you would like into fun1
Related
I have an implicit class defined in a class injected in other classes like this
class A {
implicit class B(s: String) {
def b = ???
}
}
class C(a: A) {}
Is there a way to access implicit class B (and in particular its method b) from the class C, without importing it explicitly? (Please note that class A could not be a trait since it also injects some classes.)
Solution 1 (import a._)
Well, yes, as already noted in the comments, from your requirements it is not obvious why you wouldn't just import a._ in the body of C:
class A {
implicit class B(arg: String) {
def b: String = ???
}
}
class C(a: A) {
import a._
{
println("hello".b)
}
}
This one line really doesn't hurt anyone.
If you still don't like it, then the problem might be elsewhere. Thus my second proposal.
Solution 2 (separating typeclass-like A-interface from .b-syntax)
This other solution is less about the reduction of number of imports in your code, and it doesn't even keep class B inside A. But it might address another issue that you maybe just can't quite articulate: it separates the functionality provided by A from the syntax provided by B.
The structure of the following snippet is inspired by the design of the Scala Cats library, that follows a very clear policy with the implicit declarations, always separating the typeclass defintions from the syntax.
The main idea is that:
Implementations of AIntf provide actual functionality
B provides only some additional "pimp-my-library"-style methods
and that we want to keep these two things separate.
Here is how to separate them, thereby also avoiding import a._ inside of C. First, you define the interface that describes the functionality provided by A:
trait AIntf {
def usefulOperationOnStrings(s: String): String
}
Then you can implement it by a few different A`s:
class A extends AIntf {
def usefulOperationOnStrings(s: String): String = "<foo>" + s + "</foo>"
}
class A2 extends AIntf {
def usefulOperationOnStrings(s: String): String = s.toUpperCase
}
Note that the object B has disappeared from A. Instead, it is moved in a separate syntax-package, and renamed to A_Ops. The method b is also renamed to a:
object syntax /* should be package, object only for script */ {
object a {
class A_Ops(wrapped: String, ai: AIntf) {
def a: String = ai.usefulOperationOnStrings(wrapped)
}
implicit def everyStringHasAOps(s: String)(implicit ai: AIntf): A_Ops = {
new A_Ops(s, ai)
}
}
}
This is how you use it:
You say in the imports that you want to refer to interface A_Intf
You say in the imports that you want to use the syntax syntax.a._
You declare the a-argument of C as implicit
Then you can just use "string".a syntax inside C without further imports.
In code:
import myproject.AIntf
import myproject.syntax.a._
class C(implicit val a: AIntf) {
{
println("hello".a)
}
}
Now the implementations of AIntf and the syntax .a become independent. You can inject A2 instead of A. Or you can change the syntax from "str".a to "str".somethingEntirelyDifferent.
The full code snippet:
import scala.language.implicitConversions
object myproject /* should be package, object only for script */ {
trait AIntf {
def usefulOperationOnStrings(s: String): String
}
object syntax /* should be package, object only for script */ {
object a {
class A_Ops(wrapped: String, ai: AIntf) {
def a: String = ai.usefulOperationOnStrings(wrapped)
}
implicit def everyStringHasAOps(s: String)(implicit ai: AIntf): A_Ops = {
new A_Ops(s, ai)
}
}
}
class A extends AIntf {
def usefulOperationOnStrings(s: String): String = "<foo>" + s + "</foo>"
}
class A2 extends AIntf {
def usefulOperationOnStrings(s: String): String = s.toUpperCase
}
}
import myproject.AIntf
import myproject.syntax.a._
class C(implicit val a: AIntf) {
{
println("hello".a)
}
}
val c1 = new C()(new myproject.A)
val c2 = new C()(new myproject.A2)
// prints:
// <foo>hello</foo>
// HELLO
Unfortunately, I have no clue what guice is going to do with an implicit argument, have not tried it yet. It might force you to write
class C #Inject()(val a: AIntf) {
implicit aintf: AIntf = a
...
}
which then becomes longer then the simple import mentioned in the first part.
as noted in comment, just import a._:
class A {
implicit class B(s: String) {
def b: String = "hello "+ s
}
}
class C(a: A){
import a._
val hello = "world".b
}
val c = new C(new A)
c.hello // "hello world"
This is the simplified code of a class(object) I'm working on:
object T {
val default = A
val options = List(A,B,C)
sealed trait T
object A extends T {
override def toString = "A"
}
object B extends T {
override def toString = "B"
}
object C extends T {
override def toString = "C"
}
}
This hierarchy maps directly to GUI element which requires a options = List(A,B,C) to build.
Problem with current approach:
Every time I add an extra object I have to change the option manually. This isn't too much work however the code isn't too elegant this way.
My question is:
Can I generate a list of inner objects during compile time? I wouldn't like to do this during runtime, it would be an overkill.
To add to #Samar's comment, to make it clear. The following is what you need:
import scala.reflect.runtime.universe._
case object K {
val default = A
val options = getObjects[this.type]
sealed trait T
object A extends T {
override def toString = "A"
}
object B extends T {
override def toString = "B"
}
object C extends T {
override def toString = "C"
}
def getObjects[T: TypeTag] = typeOf[T].members.collect {
case m: ModuleSymbol if m.isModule => m
}.toList
}
object GetTypeNameOfClassContainingSomeInstance {
implicit class GetsTypeNameOfContainingClass(x: Any) {
def containingClassTypeName: String = ???
}
}
class Foo {
import GetTypeNameOfClassContainingSomeInstance._
def foo(x: Any): Unit = {
println(s"${x.containingClassTypeName} owns this ${x.getClass}: $x")
// should print something like "Foo owns this <class of x>: x"
}
}
How can I make it so that containingClassTypeName knows well enough to return "Foo"?
def containingClassTypeName: String = {
val st = Thread.currentThread().getStackTrace
st(2).getClassName
}
This is an awful hack, but so is whatever you're trying to do.
I have the following trait:
trait Mappable {
def toMap = {
val mappableFields = this.getClass.getDeclaredFields.filter(...)
...
}
}
mappableFields lists this.declaredFields and then applies static filters to the list; as such it is invariant for each class that implements Mappable, and ideally I'd like to be able to put it in the subclasses' singleton objects or something along those lines. My current solution is
object Mappable {
import scala.collection.mutable.Map
private val fieldMap = Map[Class[_], Array[Field]]()
def getFieldMap(clazz: Class[_]) = {
fieldMap.get(clazz) match {
case Some(array) => array
case _ => {
val mapFields = clazz.getDeclaredFields.filter(...)
fieldMap.put(clazz, mapFields)
mapFields
}}}}
trait Mappable {
def toMap = {
val mappableFields = Mappable.getFieldMap(this.getClass)
...
}
}
but I'm wondering if there's a better solution e.g. one that doesn't require a call to Map#get. I can't turn the trait into a class.
You could do something like this:
trait Mappable {
def companion: MappableCompanion
def toMap = {
val mappableFields = companion.mappableFields
...
}
}
trait MappableCompanion {
def thisClass: Class[_]
val mappableFields = thisClass.getDeclaredFields.filter(...)
}
Subtypes of Mappable would then also define a companion object:
class Foo extends Mappable {
def companion = Foo
}
object Foo extends { val thisClass = classOf[Foo] } with MappableCompanion
If you don't like the early initializer you can make MappableCompanion a class.
I am trying to write a generic method f[T](id:String) that is something like this:
case class A(x:String)
case class B(y:String)
case class C(z:String)
def f[T](id:String): T = { /* equivalent to T(id) */ }
val result1:A = f[A]("123") // returns A("123")
val result2:B = f{B]("345") // returns B("345")
val result3:C = f[C]("567") // returns C("567")
Unfortunately I cannot figure out how to work with the type T inside the method, besides using reflection. By "working with the type T" i mean for example being able to do something like the following, which I know doesn't work (for illustration purposes only):
T match {
case A => A(id)
case B => B(id)
}
or simply invoke T(ID) to create a new object of whatever type T is.
I can of course break up this into three methods:
def f1(id:String): A = { A(id) }
def f2(id:String): B = { B(id) }
def f3(id:String): C = { C(id) }
val result1:A = f1("123") // returns A("123")
val result2:B = f2("345") // returns B("345")
val result3:C = f3("567") // returns C("567")
but I'm hoping there is a way to keep it as one generic method to avoid some ugly boilerplate code duplication, and still be nearl as fast as the tree method version.
If you do not want to use reflection (ClassTag or TypeTag), you could use a Factory type class to achieve the desired functionality (unless it defeats the purpose of your generic function by generating a lot of duplicated simple code ;)).
case class A(s: String)
case class B(s: String)
case class C(s: String)
trait Factory[T] extends ((String) => T) {
def apply(arg: String): T
}
object Factory {
implicit object AFactory extends Factory[A] {
override def apply(arg: String): A = A(arg)
}
implicit object BFactory extends Factory[B] {
override def apply(arg: String): B = B(arg)
}
implicit object CFactory extends Factory[C] {
override def apply(arg: String): C = C(arg)
}
}
def create[T : Factory](arg: String): T = implicitly[Factory[T]].apply(arg)
create[A]("foo") | -> res0: A = A(foo)