scala: Moking my scala Object that has external dependency - scala

I have a Object like this:
// I want to test this Object
object MyObject {
protected val retryHandler: HttpRequestRetryHandler = new HttpRequestRetryHandler {
def retryRequest(exception: IOException, executionCount: Int, context: HttpContext): Boolean = {
true // implementation
}
}
private val connectionManager: PoolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager
val httpClient: CloseableHttpClient = HttpClients.custom
.setConnectionManager(connectionManager)
.setRetryHandler(retryHandler)
.build
def methodPost = {
//create new context and new Post instance
val post = new HttpPost("url")
val res = httpClient.execute(post, HttpClientContext.create)
// check response code and then take action based on response code
}
def methodPut = {
// same as methodPost except use HttpPut instead HttpPost
}
}
I want to test this object by mocking dependent objects like httpClient. How to achieve this? can i do it using Mokito or any better way? If yes. How? Is there a better design for this class?

Your problem is: you created hard-to test code. You can turn here to watch some videos to understand why that is.
The short answer: directly calling new in your production code always makes testing harder. You could be using Mockito spies (see here on how that works).
But: the better answer would be to rework your production code; for example to use dependency injection. Meaning: instead of creating the objects your class needs itself (by using new) ... your class receives those objects from somewhere.
The typical (java) approach would be something like:
public MyClass() { this ( new SomethingINeed() ); }
MyClass(SomethingINeed incoming) { this.somethign = incoming; }
In other words: the normal usage path still calls new directly; but for unit testing you provide an alternative constructor that you can use to inject the thing(s) your class under test depends on.

Related

How to create mock object of main class to have partial integration test using PlaySpec?

There is a main class named 'MainProcess.scala' that I'm running some test cases for it. I wanno write an end to end test for this class to validate it's functionality.
Th problem here is the end to end test requires some criteria has to be established to be able to test whole functionality. For instance:
class MainProcess() {
def foo(someparams):Future[Boolean] = {
if criteria true else false
}
def bee(some params):Future[WSResponse] = {
// call a micro service
}
}
My question is: Is it a good practice to mock 'foo' method such that it always return true or mock 'bee' method so that test can pass through these modules and continue till it reaches the point I intend to see it's result. As I am testing this class, I know that mocking the same class results into error or malfunctionality of test case:
private def guiceApplicationBuilder(app: Application): Application = {
new GuiceApplicationBuilder()
.overrides(bind[MainProcess].toInstance(mainProcessMock))
.build()
}
If this is not a good practice, so how to do such stuff to mock specific modules of main class?
Thank you in advance.

Passing variables between Cucumber step definitions

In Cucumber, how do i go about passing variables between step definition classes. Im trying to implement in Scala.
Looking around I have seen people suggest using Guice or Picocontainer or any other DI framework. But have not really come across an example in Scala.
For instance for the example below how do I pass the variable using DI ?
Provider.scala,
class Provider extends ScalaDsl with EN with Matchers with WebBrowser {
......
When("""I click the Done button$""") {
val doneButton = getElement(By.id(providerConnectionButton))
doneButton.click()
}
Then("""a new object should be created successfully""") {
// Pass the provider ID created in this step to Consumer definition
}
}
Consumer.scala,
class Consumer extends ScalaDsl with EN with Matchers with WebBrowser {
......
When("""^I navigate to Consumer page$""") { () =>
// providerId is the id from Provider above
webDriver.navigate().to(s"${configureUrl}${providerId}")
}
}
You can use ThreadLocal to solve your problem
Here's code snippet for solution.
object IDProvider{
val providerId = new ThreadLocal[String]
def getProviderId: String = {
providerId.get()
}
def setProviderId(providerId: String): Unit = {
providerId.set(providerId)
}
}
To access providerID across different step definitions. You can simply call IDProvider.getProviderId
And to set the value of providerID, simply call IDProvider.setProviderId(PROVIDER_ID)

Specs2/Guice issue in Play 2.4.0 functional tests

I'm having an issue with dependencies apparently bleeding between tests, which is causing most of the tests to fail. In each case, debugging shows the first app created in a test class is used for all tests, and this is resulting in the failures.
I've tried adding isolated and sequential and this has had no effect.
Am I doing something remarkably stupid or subtly stupid?
For example, here's SubjectNotPresentTest.scala
class SubjectNotPresentTest extends AbstractViewTest {
"show constrained content when subject is not present" in new WithApplication(testApp(handler())) {
val html = subjectNotPresentContent(FakeRequest())
private val content: String = Helpers.contentAsString(html)
content must contain("This is before the constraint.")
content must contain("This is protected by the constraint.")
content must contain("This is after the constraint.")
}
"hide constrained content when subject is present" in new WithApplication(testApp(handler(subject = Some(user())))) {
val user = new User("foo", Scala.asJava(List.empty), Scala.asJava(List.empty))
val html = subjectNotPresentContent(FakeRequest())
private val content: String = Helpers.contentAsString(html)
content must contain("This is before the constraint.")
content must not contain("This is protected by the constraint.")
content must contain("This is after the constraint.")
}
}
GuiceApplicationBuilder is used in a parent class is used to create the app for testing.
val app = new GuiceApplicationBuilder()
.bindings(new DeadboltModule())
.bindings(bind[HandlerCache].toInstance(LightweightHandlerCache(handler)))
.overrides(bind[CacheApi].to[FakeCache])
.in(Mode.Test)
.build()
You can see an example of the failures at https://travis-ci.org/schaloner/deadbolt-2-scala/builds/66369307#L805
All tests can be found at https://github.com/schaloner/deadbolt-2-scala/tree/master/code/test/be/objectify/deadbolt/scala/views
Thanks,
Steve
It looks like the problem is caused when the current Play application is statically referenced in a test environment in which there are multiple applications - even if they are logically separate.
Because components can't be injected (to the best of my knowledge) into templates, I created a helper object which uses Play.current.injector to define a couple of vals.
val viewSupport: ViewSupport = Play.current.injector.instanceOf[ViewSupport]
val handlers: HandlerCache = Play.current.injector.instanceOf[HandlerCache]
(It's also not possible, TTBOMK, to inject into objects, otherwise I could just inject the components into the object and everyone could go home).
A better approach is to expose what is required as an implicit.
object ViewAccessPoint {
private[deadbolt] val viewStuff = Application.instanceCache[ViewSupport]
private[deadbolt] val handlerStuff = Application.instanceCache[HandlerCache]
object Implicits {
implicit def viewSupport(implicit application: Application): ViewSupport = viewStuff(application)
implicit def handlerCache(implicit application: Application): HandlerCache = handlerStuff(application)
}
}
In the view, import the implicits and you're good to go.
#import be.objectify.deadbolt.scala.DeadboltHandler
#import be.objectify.deadbolt.scala.ViewAccessPoint.Implicits._
#import play.api.Play.current
#(handler: DeadboltHandler = handlerCache(current).apply(), name: String, meta: String = null, timeout: Function0[Long] = viewSupport.defaultTimeout)(body: => play.twirl.api.Html)(implicit request: Request[Any])
#if(viewSupport.dynamic(name, meta, handler, timeout(), request)) {
#body
}

Scala design suggestion needed

I would like to design a client that would talk to a REST API. I have implemented the bit that actually does call the HTTP methods on the server. I call this Layer, the API layer. Each operation the server exposes is encapsulated as one method in this layer. This method takes as input a ClientContext which contains all the needed information to make the HTTP method call on the server.
I'm now trying to set up the interface to this layer, let's call it ClientLayer. This interface will be the one any users of my client library should use to consume the services. When calling the interface, the user should create the ClientContext, set up the request parameters depending on the operation that he is willing to invoke. With the traditional Java approach, I would have a state on my ClientLayer object which represents the ClientContext:
For example:
public class ClientLayer {
private static final ClientContext;
...
}
I would then have some constructors that would set up my ClientContext. A sample call would look like below:
ClientLayer client = ClientLayer.getDefaultClient();
client.executeMyMethod(client.getClientContext, new MyMethodParameters(...))
Coming to Scala, any suggestions on how to have the same level of simplicity with respect to the ClientContext instantiation while avoiding having it as a state on the ClientLayer?
I would use factory pattern here:
object RestClient {
class ClientContext
class MyMethodParameters
trait Client {
def operation1(params: MyMethodParameters)
}
class MyClient(val context: ClientContext) extends Client {
def operation1(params: MyMethodParameters) = {
// do something here based on the context
}
}
object ClientFactory {
val defaultContext: ClientContext = // set it up here;
def build(context: ClientContext): Client = {
// builder logic here
// object caching can be used to avoid instantiation of duplicate objects
context match {
case _ => new MyClient(context)
}
}
def getDefaultClient = build(defaultContext)
}
def main(args: Array[String]) {
val client = ClientFactory.getDefaultClient
client.operation1(new MyMethodParameters())
}
}

Custom event listener example in Grails documentation

I'm trying to add a custom GORM event listener class in Bootstrap.groovy, as described in the Grails documentation but its not working for me. Here is the code straight from the docs:
def init = {
application.mainContext.eventTriggeringInterceptor.datastores.each { k, datastore ->
applicationContext.addApplicationListener new MyPersistenceListener(datastore)
}
}
When I run it, the compiler complains that application and applicationContext are null. I've tried adding them as class level members but they don't get magically wired up service-style. The closest I've got so far is:
def grailsApplication
def init = { servletContext ->
def applicationContext = servletContext.getAttribute(ApplicationAttributes.APPLICATION_CONTEXT)
grailsApplication.mainContext.eventTriggeringInterceptor.datastores.each { k, datastore ->
applicationContext.addApplicationListener new GormEventListener(datastore)
}
}
But I still get errors: java.lang.NullPointerException: Cannot get property 'datastores' on null object.
Thanks for reading...
EDIT: version 2.2.1
If you do:
ctx.getBeansOfType(Datastore).values().each { Datastore d ->
ctx.addApplicationListener new MyPersistenceListener(d)
}
This should work without needing the Hibernate plugin installed
That looks like it should work, although I'd do it a bit differently. BootStrap.groovy does support dependency injection, so you can inject the grailsApplication bean, but you can also inject eventTriggeringInterceptor directly:
class BootStrap {
def grailsApplication
def eventTriggeringInterceptor
def init = { servletContext ->
def ctx = grailsApplication.mainContext
eventTriggeringInterceptor.datastores.values().each { datastore ->
ctx.addApplicationListener new MyPersistenceListener(datastore)
}
}
}
Here I still inject grailsApplication but only because I need access to the ApplicationContext to register listeners. Here's my listener (simpler than what the docs claim the simplest implementation would be btw ;)
import org.grails.datastore.mapping.core.Datastore
import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent
import org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener
class MyPersistenceListener extends AbstractPersistenceEventListener {
MyPersistenceListener(Datastore datastore) {
super(datastore)
}
protected void onPersistenceEvent(AbstractPersistenceEvent event) {
println "Event $event.eventType $event.entityObject"
}
boolean supportsEventType(Class eventType) { true }
}
Finally stumbled onto a working Bootstrap.groovy, thanks to this post but I don't think its the best way to do it, rather its a work around.
def init = { servletContext ->
def applicationContext = servletContext.getAttribute(ApplicationAttributes.APPLICATION_CONTEXT)
applicationContext.addApplicationListener new GormEventListener(applicationContext.mongoDatastore)
}
So basically I'm hard-coding the MongoDB datastore directly as opposed to iterating over the available ones, as the docs suggest.
To save you reading the comments to the first answer, the adapted version I provided in the Question (as well as Burt's answer) only works if the Hibernate plugin is installed but in my case I was using the MongoDB plugin so had no need for the Hibernate plugin (it in fact broke my app in other ways).