简体   繁体   中英

How to test java reflections code using JUnit

I have a java class that invoke a method via reflection. That method create database connection and perform database operations. i want to test my reflections code using junit. Is there any way to do that?

Please find my code snippet below.

    Class DaoImpl {

    public void setResult(String result) {
        this.result = result
    }

    public String getResult() {
        return this.result;
    }

    public void doDBoperation() {
        Connection connection = getConnection();
        Statement st = connection.createStatement();
        ResultSet rs = st.executeQuery("Select column_name from table");
        if(rs.next()) {
            result = "value";
        }
    }
}


Class ReflectionClass {

    public void invoke() {
        Class<?> noParam = {};

        Class<?> clazz = Class.forname("DaoImpl");
        Method method = clazz.getDeclaredMethod("doDBoperation", noParam);

        method.invoke(clazz.getNewInstance);
        System.out.println("This is it");
    }
}

How to write JUnit test case for my ReflectionClass?

There is no real "pure unit test" way of testing *ReflectionClass**. Normally, you would do a unit test by providing a mocked instance of that class to your production code; then you could use the mocking framework to verify that the expected method was called.

But in your case, you created code that is simply hard to test (if you want to learn how to address that part, you might want to watch these videos ). You are basically calling "new" directly in your production code; thus there is no way to insert a mocked object. And beyond that, you also can't mock those reflection methods.

The only option to maybe get this code tested would be to use Mokito together with PowerMock. But I am not an expert in that area, and can't promise you that it will work.

My recommendation to you: step back first and figure if you can get away from using reflection, or at least: to separate concerns here. Because as said: your production design looks weird ; and instead of spending hours to get that somehow unit tested; you should rather spent a fraction of that time to improve your design! "Hard to test" typically means "design could be improved"!

Meaning: first you create an interface that denotes the function that you want to test. Then you separate your production code of ReflctionClass , like:

  1. One part is responsible for providing an instance of that interface (and that code could be using reflection to do its job, if that is really required)
  2. The other part then calls the method(s) you want to be called on that interface object.

By doing so, you get two parts that you can test independently of each other!

Edit: what I mean by "bad design" - why are you using reflection to do both - object creation and method invocation ? You see, you could simply cast that created object to its correct class (at least if you have an interface defined there) and then do a ordinary method call on that typed object.

As @GhostCat suggested PowerMockito could be used to try to mock DaoImpl 's constructor. Here's the code:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(ReflectionClass.class)
public class ReflectionClassTest {

  @Test
  public void invoke() throws Exception {

    DaoImpl mockedDaoImpl = PowerMockito.mock(DaoImpl.class);
    PowerMockito.whenNew(DaoImpl.class).withNoArguments().thenReturn(mockedDaoImpl);
    new ReflectionClass().invoke();
    Mockito.verify(mockedDaoImpl, Mockito.atLeastOnce()).doDBoperation();
  }
}

But, it doesn't work. PowerMock doesn't manage to mock the constructor when invoked through reflection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM