Mock a method inside a service class which is under unit test

3.1k views Asked by At

I have a service class which has 2 methods(one is public and other is protected). I am trying to unit test my code. Below is the code snippet MyServiceClass.groovy

class MyServiceClass {

       public boolean myMethod1() {
            // some code
            boolean success = myMethod2()
            // some code
       }

      public boolean myMethod2() {
          // some logic to return true/false
          return true
      }

}

MyServiceClassTests.groovy

class MyServiceClassTests {

      void testMyMethod1() {
           // unit test code
      }

}

In the above unit test code, I want to mock the myMethod2() return result which is invoked by myMethod1(), i.e., both the methods are in the same service class which is under unit test. How to mock it and get things done??

3

There are 3 answers

0
curriegrr On

Have you tried to metaClass?

service.metaClass.myMethod2 = { return whatever }

http://groovy.codehaus.org/JN3525-MetaClasses

I abuse metaClass probably more than I should but it's great when you can't come up with a better way of doing things.

3
Brad On

You certainly can't mock the class under test, otherwise you're just testing a mock.

You will probably be better off, moving myMethod2() into another class. Think about whether MyServiceClass is trying to do too much.

EDIT

You have asked for an answer that doesn't require moving myMethod2()

Option 1

Create a new sub class to to be the class under test instead of MyServiceClass. Your new class should extend MyServiceClass, then you can override myMethod2() and provide a different "test only" implementation.

Option 2

It is possible to use Mockito to Spy the class under test, but this is rather an unorthodox approach.

I still recommend refactoring the code if you have the control

0
Pila On

There is this very cool trick where you can mock selected methods of a service while maintaining the general integrity of the service like so...

def method1(){
    ...
   def result = method2(param)
   return result
}


def method2(Type param){
    ...
   return result
}


void "Test method1"() {
        given:

        def service = [
                method2: {Type param -> [1,2,3,4]}
        ] as MyService

        when:
            def result = service.method1()

        then:
            result.count == 4
            result == [1,2,3,4]
 }

What I am saying in essence is, you can mock methods of a service by defining a map containing the method names as keys and a closure containing the parameter and mock values as values.