Skip to content

Kornel/ComponentUnderTest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Easier mocking of dependencies

Quickstart

ComponentUnderTest creates the mocks in your tests for you! For a running example to see yourself clone this project and launch:

src/test/java/org/kornel/testing/it/ComponentUnderTestRuleIntegrationTest.java

So, what is this all about?

Ever got tired of manually specifying mocks for your components under test? Imagine a business component:

@Component
public class BusinessProcessor {

    @Inject
    private InvoiceRepository repository;
    
    @Inject
    private InvoiceValidation invoiceValidation;    
    
    public ProcessedInvoices processInvoices() throws InvoicesAlreadyProcessed {
        final Invoices invoices = repository.fetch();
        invoiceValidation.assertUnprocessed(invoices);
        return process(invoices);
    }

}

and a test:

@RunWith(MockitoJUnitRunner.class)
public class BusinessProcessorTest {

    @InjectMocks
    private final BusinessProcessor processor = new BussinessProcessor();

    @Mock
    private InvoiceRepository repository;
    
    @Mock
    private InvoiceValidation invoiceValidation;        
    
    @Test(expect=InvoicesAlreadyProcessed.class)
    public void shouldNotProcessAlreadyProcessedInvoices() throws InvoicesAlreadyProcessed {
        // given
        given(repository.fetch()).willReturn(...)
        given(invoiceValidation.assertUnprocessed(...)).willThrow(...)
        
        // when
        processor.processInvoices()
        
        // then
        // exception        
    }
}

Specifing each of the mocks is a too repetitive and daunting task. Imagine the test looked as follows:

public class BusinessProcessorTest extends TestBase {

    @ComponentUnderTest
    private BusinessProcessor processor;
    
    @Test(expect=InvoicesAlreadyProcessed.class)
    public void shouldNotProcessAlreadyProcessedInvoices() throws InvoicesAlreadyProcessed {
        // given
        given(processor.repository.fetch()).willReturn(...)
        given(processor.invoiceValidation.assertUnprocessed(...)).willThrow(...)
        
        // when
        processor.processInvoices()
        
        // then
        // exception        
    }
}

The dependencies are mocked automatically for you! This is accomplished by:

  • A JUnit rule which scans for a ComponentUnderTest object in your tests (defined in TestBase in this examples)
  • The object is then scanned for fields annotated with a specific annotation (e.g. @Inject or @Autowired)
  • The fields are mocked using e.g. Mockito.mock

This approach requires the dependencies injected in your tests component to be package scope (assuming the test is in the same package as the tested component, which it should), but that does not seem as a too big sacrifice for the purpose of easier, quicker and more efficient TDD.

The package scoped dependencies allow for easier stubbing:

given(processor.repository.fetch())

About

JUnit rule to support component testing with Mockito

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages