Monthly Archives: November 2016

TestNg: When will @BeforeClass, @BeforeMethod, @BeforeTest be run and in what sequence?

public class KentNg {


    @DataProvider(name = "someData")
    public Object[][] someData() {
        return new Object[][]{
                {"a1", "b1"},
                {"a2", "b2"}
        };
    }

    @BeforeTest
    public void setupBeforeTest() {
        System.out.println("setupBeforeTest() is run");
    }


    @BeforeClass
    public void setupBeforeClass() {
        System.out.println("setupBeforeClass() is run");
    }

    @BeforeMethod
    public void setupBeforeMethod() {
        System.out.println("setupBeforeMethod() is run");
    }

    @Test(dataProvider = "someData")
    public void foo(String a, String b) {
        System.out.println("foo() is run");
    }


    @Test(dataProvider = "someData")
    public void bar(String a, String b) {

        System.out.println("bar() is run");
    }
}

And output is

setupBeforeTest() is run
setupBeforeClass() is run
setupBeforeMethod() is run
bar() is run
setupBeforeMethod() is run
bar() is run
setupBeforeMethod() is run
foo() is run
setupBeforeMethod() is run
foo() is run

Mockito.spy() will not work with cglib-enhanced objects

Mockito.spy() will not work with cglib-enhanced objects , even if you use doReturn() instead of thenReturn().

This can cause problems in spring + @Transactional + cblig situations.

As a result, you can’t simply use @Transactional in your code, but use TransactionTemplate, or create one interface/one implementation for every class that maybe mocked in integration tests

For integration testing’s sake, use one interface + one implemenation

With mocking technology today, you may dismiss the idea of ‘one interface + one implementation’ paradigm.

In fact, you may still appreciate this way of code organization.

Let me ask you a question: how to test a non-public method ?

For unit tests, you can set the method as package-private, and put your unit test class under the same package.

But for integration tests, normally you don’t put the integration test classes under the same package. Even if you do, when you need to mock some non-public methods of a dependent class which is not in the same package, you won’t get what you want. Take a look at the following example:

package service;

import dao.DAO;

public class Service {

    DAO dao;


    public void doSth(){
        dao.insertSth();
    }
}

package dao;


public class DAO {

    public void insertSth() {
        String thing = findOut();
        //insert it...
    }

    private String findOut() {
        return "blabla";
    }


}

You want to integration test Service.doSth(), and you want to mock DAO.findOut(). What to do? You have 3 options

  • mock DAO.findOut() anyway, which involves java reflection
  • change DAO.findOut() to a protected method , create a mocking subclass to override the method, and inject this class to Service
  • change DAO.findOut() to a public method

 

The problem of option1 is that it makes findOut() refactor-unfree. The IDE won’t know that this method is referenced by some integration test when you change the name of it.
Option2 is acceptable, but writing a subclass is not so "clean", especially when IoC framework is used.
Option3 is the easiest way, but it is really awkward to expose a private API as a public method

As a purist, you can’t accept Option3. However, you may be willing to bend the rule a little bit. And that’s our solution:

//make DAO an interface
public interface DAO {
    public void insertSth();
}


public class DAOImpl implements  DAO {

    @Override
    public void insertSth() {
        String thing = findOut();
        //insert it...
    }

    //make this method public and mock it in your test
    public String findOut() {
        return "blabla";
    }

}

Let the method being mocked be a public method in the implementation class !
Since it’s public, it can be mocked easily in test code; And serious consumer of DAO will ignore the implementation, so DAOImpl.findOut() won’t be called in any serious code. Problem solved.

Collect an inner method’s arguments and returned values with Mockito in integration tests

Imagine you have these two classes:

    public static class Manager {

        private Worker Worker = new Worker();

        public void dailyWork() {
            System.out.println("Good morning");
            String msg = RandomStringUtils.randomAlphabetic(10);
            Worker.echoTwice(msg);
            System.out.println("See you tomorrow");
        }

        public void setWorker(Worker Worker) {
            this.Worker = Worker;
        }

        public Worker getWorker() {
            return Worker;
        }
    }


    public static class Worker {

        public String echoTwice(String msg) {
            return msg + "-" + msg;
        }
    }

And you are integation testing the Manager class. How can you extract the arguments and returned values of Worker.echoTwice() ? You can create a subclass of Worker and inject an instance of it to Manager. However, this is not so "clean".

Another way of doing this is to leverage Mockito’s "Answer" feature

   
    @Test
    public void test() {
        Manager manager = new Manager();


        Worker stubbedWorker = spy(manager.getWorker());
        manager.setWorker(stubbedWorker);
        final List<String> argumentBag = new ArrayList<String>();
        final List<String> returnedValueBag = new ArrayList<String>();


        doAnswer(invocation -> {
            argumentBag.add(invocation.getArgumentAt(0, String.class));
            String returnedValue = (String)invocation.callRealMethod();
            returnedValueBag.add(returnedValue);
            return returnedValue;
        }).when(stubbedWorker).echoTwice(Mockito.anyString());


        manager.dailyWork();

        System.out.println(argumentBag.get(0));
        System.out.println(returnedValueBag.get(0));
    }