This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Mock Objects in Play[2.0]
I am learning Scala and playframework, while developing a simple application. One thing frustrates me. I have strong C# background, and used to unit testing in classical terms - mocking underlying services and test only the code in the given class.
And the question is - how to unit test a playframework application written is Scala? The way of testing proposed by playframework manual - is an integration tests, which are good, but not the thing I need. Particulary - how to mock the data access layer?
Creating mock objects is usually needed when you can not isolate your tests by having to load too many dependencies in your application before testing. You don't have that limitation when you test your data access layer in Play 2.X. Therefor, all you need to do is to use Specs2 Specification and load the in-memory database using FakeApplication(additionalConfiguration = inMemoryDatabase()
A complete test could then be written like this:
class ProjectSpec extends Specification {
"Project model" should {
"be created with id and name" in {
running(FakeApplication(additionalConfiguration = inMemoryDatabase())) {
val beforeCount = Project.count
val project = Project.create(Project("Test name", "Test description"))
project.id must beSome
project.name must equalTo("Test name")
Project.count must equalTo(beforeCount + 1L)
}
}
}
}
Related
I have a CacheService class that uses an instance of the scala-redis library
class CacheService(redisClient: RedisClient) extend HealthCheck {
private val client = redisClient
override def health: Future[ServiceHealth] = {
client.info
...
}
In my unit test, I'm mocking the client instance and testing the service
class CacheServiceSpec extends AsyncFlatSpec with AsyncMockFactory {
val clientMock = mock[RedisClient]
val service = new CacheService(clientMock)
"A cache service" must "return a successful future when healthy" in {
(clientMock.info _).expects().returns(Option("blah"))
service.health map {
health => assert(health.status == ServiceStatus.Running)
}
}
}
yet I'm getting this compilation error
Error:(10, 24) method pipeline overrides nothing.
Note: the super classes of <$anon: com.redis.RedisClient> contain the following, non final members named pipeline:
def pipeline(f: PipelineClient => Any): Option[List[Any]]
val clientMock = mock[RedisClient]
My research so far indicates ScalaMock 4 is NOT capable of mocking companion objects. The author suggests refactoring the code with Dependency Injection.
Am I doing DI correctly (I chose constructor args injection since our codebase is still relatively small and straightforward)? Seems like the author is suggesting putting a wrapper over the client instance. If so, I'm looking for an idiomatic approach.
Should I bother with swapping out for another redis library? The libraries being actively maintained, per redis.io's suggestion, use companion objects as well. I personally think this is is not a problem of these libraries.
I'd appreciate any further recommendations. My goal here is to create a health check for our external services (redis, postgres database, emailing and more) that is at least testable. Criticism is welcomed since I'm still new to the Scala ecosystem.
Am I doing DI correctly (I chose constructor args injection since our
codebase is still relatively small and straightforward)? Seems like
the author is suggesting putting a wrapper over the client instance.
If so, I'm looking for an idiomatic approach.
Yes, you are right and this seems to be a known issue(link1). Ideally, there needs to a wrapper around the client instance. One approach could be to create a trait that has a method say connect and extend it to RedisCacheDao and implement the connect method to give you the client instance whenever you require. Then, all you have to do is to mock this connection interface and you will be able to test.
Another approach could be to use embedded redis for unit testing though usually, it is used for integration testing.You can start a simple redis server where the tests are running via code and close it once the testing is done.
Should I bother with swapping out for another redis library? The
libraries being actively maintained, per redis.io's suggestion, use
companion objects as well. I personally think this is is not a problem
of these libraries.
You can certainly do that. I would prefer Jedis as it is easy and it's performance is better than scala-redis(while performing mget).
Let me know if it helps!!
I want to mock Utilities function dynamoDBStatusWrite so that when my spark program will run, it will not hit the DynamoDB.
Below is my mocking and test case stuff
class FileConversion1Test extends FlatSpec with MockitoSugar with Matchers with ArgumentMatchersSugar with SparkSessionTestWrapper {
"File Conversion" should "convert the file to" in {
val utility = mock[Utilities1]
val client1 = mock[AmazonDynamoDB]
val dynamoDB1 =mock[DynamoDB]
val dynamoDBFunc = mock[Utilities1].dynamoDBStatusWrite("test","test","test","test")
val objUtilities1 = new Utilities1
FieldSetter.setField(objUtilities1,objUtilities1.getClass.getDeclaredField("client"),client1)
FieldSetter.setField(objUtilities1,objUtilities1.getClass.getDeclaredField("dynamoDB"),dynamoDB1)
FieldSetter.setField(objUtilities1,objUtilities1.getClass.getField("dynamoDBStatusWrite"),dynamoDBFunc)
when(utility.dynamoDBStatusWrite("test","test","test","test")).thenReturn("pass")
assert(FileConversion1.fileConversionFunc(spark,"src/test/inputfiles/userdata1.csv","parquet","src/test/output","exec1234567","service123")==="passed")
}
}
My spark program should not try to connect dynamoDB. but is trying to connect
You have 2 problems there, for starters the fact that you mock something doesn't replace it automatically in your system, you need to build your software so components are injected and so in the test you would be providing a mock version of them. ie, fileConversionFunc should receive another parameter with the connector to Dynamo.
That said, it's considered a bad practice to mock library/3rd party classes, what you should do there is to create your own component that encapsulates the interaction with Dynamo, and then mock your component, as it's an API you control.
You can find a detailed explanation of why here
I am learning how to do unit tests with scalatest , but I have some basic questions as I am learning Scala/Scalatest
I wrote one scala script which has one scala object with several methods. My question is as follows: Should I write one unit test for the whole Scala object or should I write a test per function.
For example I wrote the following function :
Do you know how to write a test with scala test for this specific function:
def dataProcessing (input: List[String]) = {
val Data = input.map(_.trim).filter(x => !(x contains "$")).filter(line => Seq("11", "18").exists(s => line.contains(s))).map(elt => elt.replaceAll("""[\t\p{Zs}\.\$]+""", " ")).map(_.split("\\s+")).map(x => (x(1),x(1),x(3),dataLength(x(3)),dataType(x(3))))
return Data
}
Finally I am trying to use the test driven design best practices but still don't know how to proceed to write tests before writing code , Any tips how to proceed to be compliant with these practices.
Many thanks
In general, when you define a class or object, you should write tests for the methods someone using that class should call, and the other methods should be private. If you find yourself wanting to make methods public, just so they can be tested, consider moving them to a separate class or object.
There are a lot of testing styles supported by scala test. Personally, I like WordSpec. A basic test in progress would look like this:
class MyTest extends WordSpec with Matchers {
"My Object" should {
"process descriptors" when {
"there is one input" in {
val input = List("2010 Ford Mustang")
val output = MyObject.descriptorProcessing(input)
output should have length 1
output.head shouldBe()
}
"there are two inputs" in pendingUntilFixed {
val input = List("Abraham Joe Lincoln, 34, President",
"George Ronald Washington, 29, President")
val output = MyObject.descriptorProcessing(input)
output should have length 2
output.head shouldBe()
}
}
"format descriptors" when {
"there is one input" in pending
}
}
}
I've used two features of scalatest that enable TDD, pendingUntilFixed and pending.
pendingUntilFixed lets you write a test for code that hasn't been implemented yet, or isn't working correctly yet. As long an assertion in the test fails, the test is ignored and displayed in yellow output. Once all the assertions pass, the test fails, letting you know that you can turn it on. This enables TDD, while allowing your build to pass before work is completed.
pending is a marker saying "I'm going to write a test for this, but I haven't gotten to it yet". I use this a lot, as it allows me to write an outline for my tests, then go back and fill them in.
Is there a way to write tests for the data access objects (DAOs) in play framework 2.x without starting an app?
Tests with fake app are relatively slow even if the database is an in-memory H2 as the docs suggests.
After experiencing similar issues with execution time of tests using FakeAplication I switched to a different approach. Instead of creating one fake app per test I start a real instance of the application and run all my tests against it. With a large test suite there is a big win in total execution time.
http://yefremov.net/blog/fast-functional-tests-play/
For unit testing, a good solution is mocking. If you are using Play 2.4 and above, Mockito is already built in, and you do not have to import mockito separately.
For integration testing, you cannot run tests without fake application, since sometimes your DAOs probably require application context information, for example the information defined in application.conf. In this case, you must setup a FakeApplication with fake application configuration so that DAOs have that information.
This sample repo,https://github.com/luongbalinh/play-mongo/tree/master/test, contains tests at service and controller layers, including both unit tests with Mockito and integration tests. Integration tests for DAOs should be very similar to the service tests. Hopefully, it gives you a hint of how to use Mockito to write DAO tests.
Turns out the Database object can be constructed directly from the Databases factory, so ended up having a trait like this one:
trait DbTests extends BeforeAndAfterAll with SuiteMixin { this: Suite =>
val dbUrl = sys.env.getOrElse("DATABASE_URL",
"jdbc:postgresql://localhost:5432/testuser=user&password=pass")
val database = Databases("org.postgresql.Driver", dbUrl, "tests")
override def afterAll() = {
database.shutdown()
}
}
then use it the following way:
class SampleDaoTest extends DbTests {
val myDao = new MyDao(database) //construct the dao, database is injected so can be passed
"read form db" in {
myDao.read(id = 123) mustEqual MyClass(123)
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
We went through online material such as scalatest site. What are advantages of using scala testing framework Specs2? How does it add to the project over JUnit?
I'm a little reluctant to answer this because it's a quite subjective thing.
But I could summarise it as "In the same way Scala gives you new and cleaner ways to solve problems over Java, Specs2 gives you new and cleaner ways to test over JUnit".
Some quick examples:
Mockito is a first-class citizen
Mockito is my favourite JVM mocking library; using it with Specs2 is as simple as mixing in a trait and you get a nice DSL for verification:
class MySpec extends Specification with Mockito {
// Setup:
val mockConnection = mock[Connection]
...
// Verification: (in a test)
there was one(mockConnection).get("www.google.com")
}
ScalaCheck is a first-class citizen
ScalaCheck can save a heap of time "fuzzing" inputs to your functions, and again, a simple trait mixin gets you all of its power within your Specs2 tests.
Run a test in a Scope
Ever had a problem where tests would work on your machine but break elsewhere, because your machine ran them in a certain order? Or got into "mocking hell" due to interactions between stubbed collaborator behaviour? Specs2 lets you put the entire test into a Scope to contain all of that state and stop it from leaking into other tests:
class AnotherSpec extends Specification with Mockito {
class FooScope extends Scope {
val mockResponse = mock[Response]
val mockConnection = mock[Connection]
...
mockConnection.execute returns mockResponse
def frobulate(s:String) = {
// Use mockResponse, mockConnection, etc ...
}
}
"My thing" should {
"Do stuff" in new FooScope {
frobulate("hello")
there was one(mockConnection).post(...)
}
}
Scopes help you DRY up your tests as well as stop state leaks between them.
Plus
"Blocks" to group related tests ("My thing" should)
Readable, space-separated test names ("throw an exception if argument < 0" in)
Readable DSL for matching (result must have length(7))
Matchers for Scala-idiomatic types (result must beNone)
Easily temporarily disable a test with pending
Generate HTML reports/output with a DSL
Downsides
In an attempt to make this answer slightly more objective, I should also point out this article by the esteemed Bill Venners about compile time which points out that a Specs2 mutable.Specification, due to large numbers of implicits and function declarations, is almost an order-of-magnitude slower to compile than a roughly-equivalent JUnit test. It also does not scale well over large numbers of tests. Or at least it didn't when the article was written in early 2013. There are now approaches you can use to address this.