Let's say that I have this:
class Dependency1 {
def methodD1 { }
}
class Dependency2 {
val dependency1 = new Dependency1
}
def myMethod() {
val a = new Dependency1
// I want to be able to stub this
val b = a.dependency1.methodD1()
...
}
I want to do something like in RR (ruby mock library):
any_instance_of(Dependency1) do | obj |
stub(obj) { "123" } # this would be like stub(obj) toReturn("123") with Mockito in Scala
end
I know that there is an any method in Mockito but it's a matcher. I'm looking for something like:
stub(anyInstanceOf(Dependency1).methodD1) toReturn("123")
Is there a way to mock/stub a local dependency with Mockito/EasyMock/PowerMock/JMock ?
I'm using ScalaTest with MockitoSugar.
I know this is Scala, not Java; but if you have a look at the Mockito wiki article at http://code.google.com/p/mockito/wiki/MockingObjectCreation, it describes how to solve this in Java. I imagine the Scala solution will be much the same.
Related
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
I'm using scalatest and when I test my code, I want to replace an implementation of a function to return something else when running tests.
In JavaScript its really simple and I thought I could do the same in scala.
So what I want is something like this:
object Module {
private def bar(): Int = {
5
}
def foo(): Unit = {
println(bar())
}
}
And the test will be something like that (dont mind the syntax, you get the idea)
class Test extends FunSpec {
mock(Module.bar, () => 1)
describe("Test") {
it("Test") {
Module.foo() // will print 1
}
}
}
I have searched the internet and came across scala mock libraries but none of them seemed to be able to replace the implementation of a method.
In every library you have to defined your mock in the test and pass it on to the code, but I don't want to do that.
Is there anyway to achieve this?
Thank you.
You can't mock Object in Scala, because it's like a static class in java (which you can't mock either). (and you can't mock scala objects not in mockito nor scalamock (maybe in their next version)).
But, if you change your object Module to class Module, you can mock this function easily (using mockito):
val mockModule = mock[Module]
when(mockModule.bar()).thenReturn(1)
You can do a fake class that has that function and put the value you want, if you dont want to use mocks, like this:
trait SMT{
def bar: Int
}
class RealImpl extends SMT{
def bar: Int = 5
}
class FakeImpl extends SMT{
def bar: Int = 1
}
So I have the following bit of code
class MetricsLogger {
def measure[T](name:String)(operation: => T): T = {
val startTime = System.currentTimeMillis
val result = try {
operation
} finally {
logMetric(Metric(name, System.currentTimeMillis - startTime, StandardUnit.Milliseconds))
}
result
}
}
Where log Metric is some kind of side effect (e.g. upload metric to cloudwatch).
Now I am doing this like
def measuredOp = measure("metricName") { someOperation }
Here some operation is making some network calls.
Now I have to stub measured op.
So my stub is as the follows:-
val loggingMetrics = mock[MetricsLogger] // mock is from MockitoSugar trait
and my stubbing is like
Mockito.when(loggingMetrics.measure(Matchers.anyString())(Matchers.anyObject())).thenReturn(???)
So obviously my stubbing is wrong, but I cannot figure how to stub this properly.
Mockito doesn't support that as by-name parameters it's a concept that doesn't exists in Java, however, mockito-scala does support this from version 0.4.0 (try 0.4.0 or 0.4.2, ignore 0.4.1)
I just run a quick test like this
import org.mockito.{ MockitoSugar, ArgumentMatchersSugar }
class StackOverflowTest extends WordSpec with MockitoSugar with scalatest.Matchers with ArgumentMatchersSugar {
"mock[T]" should {
"it should work with by-name params" in {
val loggingMetrics = mock[MetricsLogger]
when(loggingMetrics.measure(any)(any)).thenReturn("it worked!")
loggingMetrics.measure("test")("") shouldBe "it worked!"
}
}
}
Disclaimer: I'm a maintainer of that library although it's part of the official Mockito suite
I'm using Scala 2.10, specs2 and Mockito. I want to mock scala.io.Source.fromURL(). The issue seems to be fromURL() is a function in io.Source's object.
val m = mock[io.Source]
m.fromURL returns io.Source.fromString("Some random string.")
It's a pretty straightforward mock in an Unit test. Why isn't it working?
Thanks!
Instead of mocking it, you could try spying it as follows:
val m = spy(io.Source)
Or you could mock it as follows:
val m = mock[io.Source.type]
But then how are you using Source in the class you are testing? If you had an example class like so:
class MyClass{
def foo = {
io.Source.doSomething //I know doSomething is not on Source, call not important
}
}
Then in order to take advantage of mocking/spying, you'd have to structure your class like so:
class MyClass{
val source = io.Source
def foo = {
source.doSomething
}
}
And then your test would have to look something like this:
val mockSource = mock[io.Source.type]
val toTest = new MyClass{
override val source = mockSource
}
In the Java world, static methods are the bane of mocking. In the Scala world, calls to objects can also be troublesome to deal with for unit tests. But if you follow the code above, you should be able to properly mock out an object based dependency in your class.
Good news! With the latest 1.16 release of mockito-scala, you can now mock scala objects.
To enable withObjectMocked feature, it is mandatory to create the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line:
mock-maker-inline
Example:
object FooObject {
def simpleMethod: String = "not mocked!"
}
"mock" should {
"stub an object method" in {
FooObject.simpleMethod shouldBe "not mocked!"
withObjectMocked[FooObject.type] {
FooObject.simpleMethod returns "mocked!"
//or
when(FooObject.simpleMethod) thenReturn "mocked!"
FooObject.simpleMethod shouldBe "mocked!"
}
FooObject.simpleMethod shouldBe "not mocked!"
}
}
See: https://github.com/mockito/mockito-scala#mocking-scala-object
Years later, above answer doesn't work as others have pointed out.
And you cannot mock the scala.io.Source object.
Can I mock final / private methods or classes? This is not supported, as mocks generated with macros are implemented as subclasses of the type to mock. So private and final methods cannot be overridden. You may want to try using an adapter or façade in your code to make it testable. It is better to test against a trait/interface instead of a concrete implementation. There are libraries that support this kind of mocking, such as PowerMock. Be aware that this kind of mocking involves Bytecode manipulation, which has the risk that your test double diverges from the actual implementation.
So what I did is an work around to abstract out scala.io.Source.fromUrl() as a function argument and pass in mocked function in tests.
// original func
def aFuncThatUsesSource() = {
val source = scala.io.Source("127.0.0.1:8080/...")
val result = source.mkString
Try(source.close())
result
}
// test friendly func that accepts `scala.io.Source.fromURL` as arg
def aTestFriendlyFunc(makeApiCall: String => BufferedSource) = {
val source = makeApiCall("127.0.0.1:8080/...")
val result = source.mkString
Try(source.close())
result
}
....
// test spec
def testyMcTesterson = () => {
val makeApiCall = mockFunction[String, BufferedSource]
makeApiCall.expects("something...")
.returns( new BufferedSource(new ByteArrayInputStream("returns something".getBytes)) )
aTestFriendlyFunc(makeApiCall) shouldEqual "returns something"
}
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