Access to protected var of Mock class - scala

I'm using Mockito to test a scala class with a protected var. I would like to mock this var but obviously I can not access to this var via my mock class.
This is my code:
abstract class ETL_Generic(val fileCode: String, val rwSessionWrapper: RWSessionWrapper) extends Serializable {
protected var measurementsByFinalCode: scala.collection.Map[String, Measurement] = _
}
And this is the code to mock the abstract class:
val etlGenericMock = mock(classOf[ETL_Generic], withSettings().useConstructor("", rwSessionWrapperMock).defaultAnswer(CALLS_REAL_METHODS))
How can I assign a value to this var with the mock class?
Thanks.

I did an adapter extending the class to mock, overriding protected vars and then mocking this adapter.
Thanks!

Related

Play framework inherit dependency injected trait?

Is it possible to create an overloaded play.api.mvc.Controller trait that has dependency injected arguments?
For example, say I have a couple of customized Actions that require a dependency injected AuthorizationService. I would like to write my controllers like this:
class UserController extends CustomController {
def getUser(userID: String) = CustomAction {
...
}
}
However, I can't figure out how to create the CustomController trait such that it doesn't require me to inject my AuthorizationService in my UserController. Is there a way to do this with Guice?
You can inject a field into your CustomController trait. The field should'n be final so it has to be declared as var in Scala.
#Inject() var authService: AuthorizationService
You can also make the injected var private and declare a public val which references the injected field. In this case val has to be lazy since injection occurs after class was instantiated. See Guice docs for more details.
#Inject() private var as: AuthorizationService = _
lazy val authService: AuthorizationService = as
It isn't possible to inject a dependency into a trait because a trait isn't instantiable. A trait doesn't have a constructor to define the dependencies, you must inject your AuthService via UserController
Example.
trait CustomController extends Controller {
val authService: AuthService
...
}
class UserController #Inject()(override val authService: AuthService) extends CustomController {
...
}

Make constructor parameters public in subclass

I want the protected fields of a class to be made publicly visible in a subclass:
class MyClass(protected val someDao: SomeDao)
class TestMyClass extends MyClass(mock[SomeDao])
Now I want to access someDao like so:
val testClass = new TestMyClass
testClass.someDao
I've read that in Java and Scala access modifiers can be broadened but not restricted in subclasses (although these are just constructor parameters, not private fields per se). How can I achieve that in this example?
EDIT:
The answers provided suggest making someDao public in the base class. This is not what I want. I want it to remain private, but just change its visibility to public in the TestMyClass class.
As far as I know, an overriden val cannot access the super implementation.
If you can modify the base class, one solution is to explicitely define an accessor method, which can be overriden; something like this:
class MyClass(_someDao: SomeDao) {
protected def someDao = _someDao
}
class TestMyClass extends MyClass(mock[SomeDao]) {
override def someDao = super.someDao
}
If you cannot change the base class, one workaround would be to define a public accessor method with a different name:
class MyClass(protected val someDao: SomeDao)
class TestMyClass extends MyClass(mock[SomeDao]) {
def someDao2 = someDao
}
Add var or val to parameters declaration:
class MyClass(val someDao: SomeDao)
In this case only getter function will be generate for someDao field. So when you write testClass.someDao you retrieve not the someDao as field you use their getter function.
Good example about visibility of class parameters in Scala demostrated at this article.
Regarding to your last updates
Set package scope for parameter declaration:
class MyClass(private[lastPackageOfSomeDao] val someDao: SomeDao)

Guice in Scala: Module for a class that has a DI-constructor itself

I'm using codingwell/scala-guice and trying to inject DAO-classes into constructors of other components/classes.
In the first attempt, I only used one DAO-class to see if it works:
class DaoModule extends AbstractModule with ScalaModule {
override def configure() {
val dao1 = new FirstDaoImpl
bind(new TypeLiteral[FirstDaoTrait] {}).toInstance(dao1)
}
}
The binding works as expected, it can be used for constructor injection.
In the second step, I wanted to add another DAO class to the module. However, that DAO-class depends on the first DAO:
class SecondDaoImpl #Inject()(firstDao: FirstDaoTrait) extends SecondDaoTrait
I'm not sure how to add the necessary binding to the existing module. Repeating the first step would result in this:
val dao2 = new SecondDaoImpl(???)
bind(new TypeLiteral[SecondDaoTrait] {}).toInstance(dao2)
But of course this class can only be instantiated by providing the first DAO (therefore the "???"). How can I do this?
Use bind and let scala-guice resolve the dependencies for you:
class DaoModule extends AbstractModule with ScalaModule {
override def configure() {
bind[FirstDaoTrait].to[FirstDaoImpl]
bind[SecondDaoTrait].to[SecondDaoImpl]
}
}
And now using the injector:
val injector = Guice.createInjector(new DaoModule())
val secondDao = injector.instance[SecondDaoTrait]

Scala traits exposing protected members?

Given a class like:
class MyClass {
protected object MyObj { ... }
}
is it possible to write a trait that will permit exposing MyObj. E.g. with inheritance I could do the following:
class TestMyClass extends MyClass {
val getMyObj = MyObj
}
but I want to do this via a trait, something like the following which doesn't typecheck:
trait ExposeMyObj {
val getMyObj = MyObj // super.MyObj/this.MyObj don't work
}
and use it like:
class TestMyClass extends ExposeMyObj
Is it possible to reproduce the functionality in TestMyClass into a trait to expose the protected object, and if so how?
If you know that your trait will always be mixed in to an instance of MyClass (or a subclass), you can enforce the expectation with a self-type, and then access the object:
trait ExposeMyObj {
self: MyClass =>
val getMyObj = MyObj
}
Edit: an example of using this trait:
class TestMyClass extends MyClass with ExposeMyObj
val test = new TestMyClass
test.getMyObj // accesses MyObj defined in MyClass.
Edit 2: attempting to address #jbrown's comment (re: testing queries within repos) - I would look at doing something like the following - first, in each repo's file, add a trait for each repo holding the queries for that repo:
trait UserQueries { // you could look at making this protected, if you like
protected def query1(param: String) = List(param) // very silly implementation, but hopefully enough to make the point
... // other queries
}
class UserRepo extends UserQueries // Has (internal) access to those queries
Then in the test class file for a given repo:
class UserQueriesTester extends UserQueries with ScalaTest { // or whatever test framework you are using
// (public) tests to run - eg:
def testQuery1 = query1("test") should be (List("test"))
}

Unit testing trait with object

I have the following construct, where I have a
trait DataServiceLocalImpl extends DataService {
override lazy val dataService = DataComponentLocalImpl
}
object DataComponentLocalImpl extends DataComponent {
def getData(element:String):String = GetStuffFromFile(element)
}
trait DataService {
val dataService: DataComponent
}
trait DataComponent {
def getData(element:String):String
}
The GetStuffFromFile reads a file from disk once (I only want this once, hence the object), creates a map and then returns the value for element.
This is all done in an Play Framework 2.3 surrounding and the app works as well, but when I use it in a test as an implicit I get the following error:
java.lang.NoClassDefFoundError: Could not initialize class DataComponentLocalImpl
Test suite:
class AutoCompleteSpec extends PlaySpec with Mockito with OneAppPerSuite {
val resource = new DataServiceLocalImpl {}
implicit val dataService = resource.dataService
}
If I remove the implicit it works...
You should create an object with the service overriden.
object FakeImpl extends DataServiceLocalImpl {
override dataService = //Fake or test data service here
}
You then create an anonymous class definition that allows you to test the trait.