简体   繁体   中英

Writing junit(mockito) for a public method created inside a private method

I want my test to cover the code written inside afterCompletion(). I've tried mocking the public method which calls addTransactionLifeCycleMethods() , but it doesn't go inside TransactionSynchronizationManager . Here's the code snippet

private void addTransactionLifeCycleMethods(Map<Integer, ForecastRunDTO> newRunDTOs, Boolean isSystemTriggeredActualComputation) {
    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
        @Override
        public void afterCompletion(int status) {
            // Cover this using mockito
            }
        }
    });
}

Note: TransactionSynchronizationManager and TransactionSynchronizationAdapter are both abstract classes in org.springframework.transaction.support;

Elaborating on my suggestion from the comments:

First, I'd refactor the "production" code so that the TransactionSynchronizationAdapter is produced by a method:

public class MyRealClass {
    private void addTransactionLifeCycleMethods(
        Map<Integer, ForecastRunDTO> newRunDTOs, Boolean isSystemTriggeredActualComputation) {
        TransactionSynchronizationManager.registerSynchronization(
            getTransactionSynchronizationAdapter());
    }

    protected TransactionSynchronizationAdapter getTransactionSynchronizationAdapter() {
        return new TransactionSynchronizationAdapter() {
                @Override
                public void afterCompletion(int status) {
                    // Cover this using mockito
                    }
                }
            });
        };
    }

    // rest of the class....
}

You can then use mockito so spy that method and return a mock object with any arbitrary behavior you need for your test:

public class MyRealClassTest {
    private MyRealClass underTest;

    @BeforeEach
    public void setUp() {
        TransactionSynchronizationAdapter mockTSA = 
            Mockito.mock(TransactionSynchronizationAdapter.class);
        // Add behavior to the mock using Mockito.when

        underTest = Mockito.spy(new MyRealClass());
        Mockito.doReturn(mockTSA).when(underTest).getTransactionSynchronizationAdapter();
    }

    // tests ...
}
            public MainClass {
                  public void method() {
                  .......
                  addTransactionLifeCycleMethods(Map<Integer, ForecastRunDTO> newRunDTOs, Boolean isSystemTriggeredActualComputation);
                  }
                  private void addTransactionLifeCycleMethods(Map<Integer, ForecastRunDTO> newRunDTOs, Boolean isSystemTriggeredActualComputation) {
                TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                    @Override
                    public void afterCompletion(int status) {
                        // Cover this using mockito
                        }
                });
            }
       }
            
 
            Answer:
            TestClass {
            
            @InjectMocks
            MainClass manager;
            
            @BeforeEach
                public void init() {
                    TransactionSynchronizationManager.initSynchronization();
                }
            
            @AfterEach
                public void clear() {
                    TransactionSynchronizationManager.clear();
                }

            @Test
            void Test {
                   manager.method();
                   TransactionSynchronizationManager.getSynchronizations().get(0).afterCompletion(anyInt());        
            }

}

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