I have mocked a service. Service has a method 'action' which takes an object of type MyCustomObject and returns a Future of Either. So to mock:
when(myService.action(any[MyCustomObject]())).thenReturn(any[Future[Any]]())
I don't see any issue here conceptually. I am telling mockito to mock method action such that whenever it is called with any object of type MyCustomObject, then make it return a Future of Any as I don't care about value inside Future.
But it give me error:
When using matchers, all arguments have to be provided by matchers.
Both of my mocked values are generic in nature, so what's the cause of this error?
When using Mockito, you cannot pass a matcher in the thenReturn: the point of mocking is to define arbitrary return values.
Conceptually, Mockito could probably generate some random data for simple types but how would you expect Mockito to generate data for a type it doesn't know at all and maybe accept only some specific values?
TL;DR: You have to provide a return value:
when(myService.action(any[MyCustomObject]()))
.thenReturn(Future.succesfull(Right(something)))
Related
I'm working on a scala project and in my unit test I have to stub a method that takes as argument a Date(that is instanciated when calling the method), and I can't get to stub it porperly
However, I was able to find a turnaround using this post How to mock new Date() in java using Mockito
But I wonder if there is a better way to do this because I find that solution not very satisfying ...
here is the code I try to stub :
def foo(): Future[JsonObject] ={
[...]
for {
a <- b.bar(arg,atDate = Some(Date.from(Instant.now())))
} yield a
}
I tried to stub it like that
val b = mock[B]
when(b.bar(arg, _:Option[Date])).thenReturn(Future.successful(List()))
this doesn't parse,so I have to change it to :
val b = mock[B]
when(b.bar(arg, _:Option[Date])).thenReturn({ d:Date => Future.successful(List())})
and when I run it I have the following error :
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
Maybe I'm missing something in the error message but I don't find it helpful.
Is there any way to tell the stub to take whatever value for the date?
Also why does it require to put a function in thenReturn part, although the return type of the function is Future[List[A]]?
thanks in advance
You have to use the any matcher, so your code looks like (here I'm assuming arg is a variable defined somewhere else in your test code)
when(b.bar(ArgumentMatchers.eq(arg), ArgumentMatchers.any())).thenReturn(Future.successful(List()))
Now that's a bit verbose, so if you upgrade to mockito-scala and use the idiomatic syntax it would look like
b.bar(arg, *) returns Future.successful(List())
if you have/use cats, you can even do
b.bar(arg, *) returnsF List()
for more info check the docs here
I would like to write test for a controller class. The controller class takes a service object as constructor parameter. Added the #Inject annotation to the constructor of the service class.
class AssociateService #Inject()(configuration: Configuation){...}
The constructor parameter of the service class is a custom configuration object also created for the application. I added the #Inject to the constructor of the config class as well. Now I'm getting these types of error messages:
No implementation for "className" was bound.
Could not find a suitable constructor in java.lang.Integer. Classes must have either one (and only one) constructor annotated with #Inject or a zero-argument constructor that is not private.
The configuration class has several constructor parameters, those are "basic" types (Int, Boolean) and one parameter is a custom class type (className).
How should I do this binding or is it just enough to annotate something else?
And why it says that constructor error message?
As far as I know, there are two ways with tests and guice, with trade offs:
Don't using field injections, using only constructor injections and fields assignment in constructor for injected parameters. This approach enables very simple solution for testing, just don't use dependency injection in tests. But all your classes must have ability to be created with new operator in test cases...
Ps. You can define optional constructor and use field injections, of course, but it is not very clear solution.
Creating correct module with injectable interfaces binding to its implementations for every test or group of similar tests. Sometimes this approach takes a lot of unnecessary working hours.
You must design your software to maintain testability. Sometimes not every line of code in project need to be tested, sometimes not every code is testable, you must separate it from important parts of your software, that requires testing. If you design your software with single responsibility principe so writing tests is much easer...
So I want to check arguments that I send to an external class that I do not control. The external class is assumed tested, I simply want to test if I passed it the right parameters. I have tried some combination of ArgumentCaptor etc, but not much luck
import org.ABC.ExternalClass
case class Foo(i:Int, j: Int...) {
val EC = CreateExternalClass()
def CreateExternalClass(): ExternalClass = {
new ExternalClass (i, j, ....many parameters)
}
}
I think you are getting things wrong here: you can only use an ArgumentCaptor on calls to mocked objects. You can't use them to "intercept" arbitrary calls between all kinds of objects.
Meaning: you could only use an ArgumentCaptor if you would be using a mocked ExternalClass object. But then you would not need to capture, as you probably could do simply method call argument verification.
But of course, you can't use Mockito to mock that call to new in your production class. The options you have:
Turn to PowerMockito or JMockit; frameworks that allow to mock calls to new. Not recommended.
Rework your production code to not do that call to new. Probably not helpful here; as this class might already be a wrapper around that external class
Go for checking on the created object: check if you could use getter methods to simply query the newly created object to have the values that you expect to show up inside
I have a method that takes type parameters with an implicit view bounds on them. Can I use the #implicitNotFound annotation to give nicer compiler errors when the method is called with invalid data types?
The documentation for the method is useless and even the source code doesn't help, and all the examples of use online are at the trait or class level.
No, you cannot directly do that. As you’ve noticed, #implicitNotFound annotates traits or classes. You could, however, make a special implicit type just for that method and annotate it if you really wanted to have a custom message.
Is it possible to create an AOP like interceptor using Scalas new Dynamic Type feature? For example: Would it be possible to create a generic stopwatch interceptor that could be mixed in with arbitrary types to profile my code? Or would I still have to use AspectJ?
I'm pretty sure Dynamic is only used when the object you're selecting on doesn't already have what you're selecting:
From the nightly scaladoc:
Instances x of this trait allow calls x.meth(args) for arbitrary method names meth and argument lists args. If a call is not natively supported by x, it is rewritten to x.invokeDynamic("meth", args)
Note that since the documentation was written, the method has been renamed applyDynamic.
No.
In order for a dynamic object to be supplied as a parameter, it'll need to have the expected type - which means inheriting from the class you want to proxy, or from the appropriate superclass / interface.
As soon as you do this, it'll have the relevant methods statically provided, so applyDynamic would never be considered.
I think your odds are bad. Scala will call applyDynamic only if there is no static match on the method call:
class Slow {
def doStuff = //slow stuff
}
var slow = new Slow with DynamicTimer
slow.doStuff
In the example above, scalac won't call applyDynamic because it statically resolved your call to doStuff. It will only fall through to applyDynamic if the method you are calling matches none of the names of methods on the type.