How do I unit test custom tasks?

I want to unit test my custom tasks. I’ve read a few brief answers to similar questions, such as this one, which say the approach is to create integration tests using the tooling API. For my situation, this is going to be an overkill.

I was hoping there would be some way to just put unit tests in the src/test structure and test the underlying task classes more or less as POJOs. I’m able to instantiate the task class. However, I get:

org.gradle.api.internal.MissingMethodException Could not find method for() for arguments

For example:

MyCustomTask.groovy:
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
  class MyCustomTask extends DefaultTask {
   @TaskAction
  def setMyOutput(){
     println "${name} is running"
    getOutputs().files(new File("testfile.txt"))
  }
  def getHello(){
     return "hello"
  }
}
  TestMyCustomTask.groovy:
  import org.gradle.api.Project
import org.gradle.testfixtures.ProjectBuilder
import org.junit.*
  class TestMyCustomTask extends GroovyTestCase {
   def mct
  @Before
  void setUp() {
     Project p = ProjectBuilder.builder().build()
    mct = p.task(type:MyCustomTask)
    println "Setting up unit test for TestMyCustomTask "
  }
    @Test
  public void testGetHello(){
     assertTrue "not hello",mct.getHello()=="hello"
  }
}

I get:

TestMyCustomTask > testGetHello STANDARD_ERROR
    SLF4J: Class path contains multiple SLF4J bindings.
    SLF4J: Found binding in [jar:file:/C:/apps/gradle-1.8/lib/logback-classic-1.0.9.jar!/org/slf4j/impl/Static
LoggerBinder.class]
    SLF4J: Found binding in [jar:file:/C:/Users/O386600/.gradle/caches/artifacts-26/filestore/org.slf4j/slf4j-
jdk14/1.6.1/jar/251899d8c17e29ed4c53d98c88e54241a14d9591/slf4j-jdk14-1.6.1.jar!/org/slf4j/impl/StaticLoggerBin
der.class]
    SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
    SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
  TestMyCustomTask > testGetHello STANDARD_OUT
    14:50:59.219 [Test worker] DEBUG o.g.a.i.a.m.DefaultLocalMavenRepositoryLocator - No local repository in S
ettings file defined. Using default path: C:\Users\O386600\.m2\repository
    Setting up unit test for TestArfMaker
Gradle Worker 2 finished executing tests.
  TestMyCustomTask > testGetHello FAILED
    org.gradle.api.internal.MissingMethodException: Could not find method getHello() for arguments [] on task
':{type=class MyCustomTask}'.
        at org.gradle.api.internal.AbstractDynamicObject.methodMissingException(AbstractDynamicObject.java:68)
          at org.gradle.api.internal.AbstractDynamicObject.invokeMethod(AbstractDynamicObject.java:56)

Is there no way to do basic unit testing of the task class without building up an extensive testing framework?

  • Andy

It’s up to you to design the task class in such a way that it’s possible to write meaningful unit tests. You just shouldn’t assume that ‘ProjectBuilder’ will create tasks that you can call ‘Task.execute()’ on, because ProjectBuilder is not designed for executing tasks. Also I’m not sure if certain task and project methods (e.g. ‘Project.copy()’), which your task class might be calling, will work correctly.

I’m not completely sure why you are getting this particular error, but one thing that strikes me is that you are effectively passing ‘null’ for the task name. Try ‘mct = p.task(“foo”, type: MyCustomTask)’.

Another problem I can spot is that you can’t set a task’s inputs while the task is already running (i.e. in its task action).