How can I mock behaviour of new object created inside static Main?

326 Views Asked by At

IS there any way I can mock behaviour of an object created inside my Test class static method? Like, I have class like below:

class Main{
    public static void main(String[] args){
      AnnotationConfigApplicationContext cxt = new AnnotationConfigApplicationContext();
      SomeMapper map = cxt.getBean(SomeMapper.class);
      map.getData();
    }
}

The mapper 'SomeMapper' is ibatis query mapper for fetching data from DB. Can I right a test class for this method using Mockito framework? Or can just mock behaviour of mapper class or ApplicationContext class?

2

There are 2 best solutions below

2
tddmonkey On

Instead of trying to test your main method, lift the actual logic into a standard class and test that instead. Leave your main method to handle things that are explicitly concerned with launching your app. For example, you might break it up like this:

class MapperRunner {
    private SomeMapper mapper;

    public class MapperRunner(SomeMapper mapper) {
        this.mapper = mapper;
    }

    public void runMapping() {
        mapper.getData();
    }    
}

public class Main {
    public static void main(String[] args){
        AnnotationConfigApplicationContext cxt = new AnnotationConfigApplicationContext();
        SomeMapper map = cxt.getBean(SomeMapper.class);
        new MapperRunner(map).runMapping();
    }
}

With just a single method this definitely looks like overkill, but presumably your actual code does something more complex than this.

0
Alvaro Berrocal On

Maybe you need to use other approach. If you need configure the application with the values, use @Configuration class:

@Configuration
public class MyCustomConfiguration{
    
    @Autowired
    SomeMapper someMapper;

    //your code
}

In this approach you can mock the mapper in the test:

@RunWith(MockitoJUnitRunner.class)
public class MyCustomConfigurationTest{
    
    @Mock
    SomeMapper someMapper;

    @InjectMocks
    MyCustomConfiguration configuration;

    //your tests
}

Also you have a second option if you just need execute some logic. You can implement ApplicationRunner interface. This is executed on startup and you can inject the beans as a normal spring component. The code ir really similar so I'm not going to rewrite it.