Unit Test « Intelligrape Groovy & Grails Blogs

Archive for the ‘ Unit Test ’ Category

Tips for Agile Development with Unit Testing approach.

Wednesday, July 14th, 2010
Posted by salil

This is more towards the best practices and my experiences for developing an application at a faster rate.

In my current project, we are using many different APIs (for external services). And usually it takes time to explore, implement and then stabilize the application. Also, it’s not over once you stabilize your APIs based code. Because there are possibilities to have unexpected results such as server side errors, broken request, broken response, etc. Also you never know when Service provider makes some changes and your code breaks.

Well, here are some tips which really helped me to achieve faster implementation and more stable application (esp. when working with third party APIs).

TRY TO MAKE YOUR CODE UNIT TESTABLE as much as possible.

1. Create Service layer for API based implementation. Keep this service layer independent from other application. So that you should run it without any other dependency.

2. Try to make small chunks of code (in form of methods) with least dependency on external things.
Avoid Domain/Database/Environment specific code. In other words, don’t put any kind of framework specific dependency. In some cases you can’t avoid. But try to avoid as much as possible. Because it could lead to integration testing and which again takes more time. Unit test is the fastest way to check your code stability.

3. In case you have some dependencies (and that can not be avoided) – Try to mock it up. In many cases it’s possible. If you are using Grails/Groovy kind of framework/language – you have an edge to take an advantage of meta-programming.

4. There is no specific way to do this. But it comes with practice. You can follow above tips to implement your Service Layer Code. And then create unit tests – invoke your API based service methods. And run it. Wow.. that’s it.

Advantages:
If there’s any kind of changes (from service provider), that can break your application’s functionality, test driven development will work as a “Life Saver”. It can tell you where’s the problem and why it happened. And you can make appropriate changes to stabilize it again.

Same thing implements when you develop a new feature. Unit Test Case helps you see the results in few seconds. Instead of waiting for 10-15 minutes (until application starts).

Isn’t it cool?

I really appreciate this approach. Hope others will also use it.

Thanks
Salil Kalia

  • Share/Bookmark
Posted in Grails, Groovy, Test, Unit Test

Grails unit testing for beginners

Wednesday, July 14th, 2010
Posted by Imran Mir

Ques: How is unit testing different from integration testing ?

Ans: Integration tests need to bring up the whole grails environment.They talk to the database. All the dynamic GORM methods and properties are available here. Unit testing are small focused, fast loading tests that do not load supporting components.

Ques: How can I unit test a method in a service ?

Ans: You would need to follow these simple steps:

Suppose you want to write a unit test case for a someFunction() in MyService:

class MyService {
    public String myFunction() {
      return "testString"
    }
  }

-> Create Unit Test File : grails create-unit-test com.intelligrape.xxx.MyService. It will create the test file in the folder /test/unit
-> Write a testcase function
-> Create an object of MyService
-> Call the function and make assertions

public void testMyFunction() {
    def myService = new MyService()
    String string = myService.myFunction()
    assertEquals "testString", string
  }

Ques: I am saving an object from this function. How can I test that ?

 public void myFunction(int number, String name) {
    MyDomainClass object = new MyDomainClass(age: number, name: name)
    object.save()
  }

Ans: Its pretty simple. You would first need to mock the domain class whose object is being saved.

   def instances = []
   def myTestDomain = mockDomain('MyDomainClass',instances)

instances will serve as a cache of objects. Right now it contains no object. But when you call the save method from the function to be tested, it will automatically put that object in this cache. So, we can make assertions against this cache. Just to remind you, no database communication occurs during the unit testing.

 public void testMyFunction() {
    def instances = []
    def myTestDomain = mockDomain('MyDomainClass', instances)
    def myService = new MyService()
    String string = myService.myFunction(30, 'myName')
    assertEquals 1, instances.size()
  }

Ques: What does this mockDomain do ?

Ans: mockDomain is a method of GrailsUnitTestCase, that helps to mock a domain class. mockDomain also mocks most of the injected methods of the domain class like, save(), validate(),delete(),get() and many others. But there are many methods it does not mock,e.g., createCriteria,find,findAll,withTransaction and many others.

Ques: That was great. But now my function uses some other service to do some job. How can I test that ?

  public void myFunction(String empId) {
    String name = otherService.someOtherFunction(empId)
    MyDomainClass object = new MyDomainClass(name: name)
    object.save()
  }

Ans: In this case you would need to mock both, other service as well as the method which is called.

void testMyFunction() {
    def otherService = mockFor(OtherService)
    otherService.demand.someOtherFunction() {empId-> return "testName"}
    def myService = new MyService()
    myService.otherService = otherService.createMock()
    String string = myService.myFunction(30, 'myName')
    assertEquals 1, instances.size()
}

Ques: What does this mockFor method do ?

Ans: It is a method that is used to mock a dependency. We can mock services and its methods with the help of this. The demand method of the object returned by the method can be used to mock different methods of the mockedInstance. We can also specify the number of times the function is actually called in the function.

 otherService.demand.someOtherFunction(1..2) {empId; return "testName"}

Here, it means someOtherFunction() will be called not more than 2 times in the function.

Hope this helps.
Imran Mir
imran@intelligrape.com

  • Share/Bookmark
Posted in Grails, Groovy, Test, Unit Test