Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I unit test a custom ant task?

Tags:

junit

ant

I am writing a custom ant task that extends Task. I am using the log() method in the task. What I want to do is use a unit test while deveoping the task, but I don't know how to set up a context for the task to run in to initialise the task as if it were running in ant.

This is the custom Task:

public class CopyAndSetPropertiesForFiles extends Task {
    public void execute() throws BuildException {
        log("CopyAndSetPropertiesForFiles begin execute()");

        log("CopyAndSetPropertiesForFiles end execute()");
    }
}

This is the unit test code:

CopyAndSetPropertiesForFiles task = new CopyAndSetPropertiesForFiles();
task.execute();

When the code is run as a test it gives a NullPointerException when it calls log.

java.lang.NullPointerException
    at org.apache.tools.ant.Task.log(Task.java:346)
    at org.apache.tools.ant.Task.log(Task.java:334)
    at uk.co.tbp.ant.custom.CopyAndSetPropertiesForFiles.execute(CopyAndSetPropertiesForFiles.java:40)
    at uk.co.tbp.ant.custom.test.TestCopyAndSetPropertiesForFiles.testCopyAndSetPropertiesForFiles(TestCopyAndSetPropertiesForFiles.java:22)

Does anybody know a way to provide a context or stubs or something similar to the task?

Thanks,

Rob.

Accepted answer from Abarax. I was able to call task.setProject(new Project()); The code now executes OK (except no logging appears in th console - at least I can exercise the code :-) ).

like image 932
Rob H Avatar asked Oct 08 '08 08:10

Rob H


People also ask

Is Ant integrated with JUnit?

The use of Ant makes it straight forward through the JUnit task.

What does * stands for in * Test Java in ant?

**\*.sql means "in the given directory and inside all of its subdirectories, all the files that end with .sql"


2 Answers

Or better yet, decouple the task object itself from the logic (lets call it TaskImpl) inside the task - so that you can pass in your own dependencies (e.g., the logger). Then, instead of testing the task object, you test TaskImpl -> which you can pass in the logger, and any other weird bits and pieces it might need to do its job. Then unit testing is a matter of mocking the dependencies.

like image 127
Chii Avatar answered Sep 22 '22 00:09

Chii


Looking at the Ant source code these are the two relevent classes: ProjectComponent and Task

You are calling the log method from Task:

public void log(String msg) {
     log(msg, Project.MSG_INFO);
}

Which calls:

public void log(String msg, int msgLevel) {
  if (getProject() != null) {
    getProject().log(this, msg, msgLevel);
  } else {
    super.log(msg, msgLevel);
  }
}

Since you do not have project set it will call "super.log(msg, msgLevel)"

public void log(String msg, int msgLevel) {
  if (getProject() != null) {
     getProject().log(msg, msgLevel);
  } else {
    // 'reasonable' default, if the component is used without
    // a Project ( for example as a standalone Bean ).
    // Most ant components can be used this way.
    if (msgLevel <= Project.MSG_INFO) {
      System.err.println(msg);
    }
  }
}

It looks like this may be your problem. Your task needs a project context.

like image 23
abarax Avatar answered Sep 18 '22 00:09

abarax