Whether and how to test façades

by Hubert Grzeskowiak   Last Updated October 16, 2017 11:05 AM

In my application I have quite a few service classes that act as a façade and delegate most calls to one or more underlying manager classes. I've read very different opinions on how to test such façades. Some people say it's not necessary to test them at all, others say one should test whether the integration is working.

I've implemented two test methods for the delegating method below. One test is checking whether the underlying manager method has been called exactly once, the other test checks whether the passed data is equal (or in this case: the same).

@Stateless
public class ApplicationService {

    @Inject
    ApplicationManager applicationManager;

    public List<Application> getApplicationsList() {
        return applicationManager.getApplications();
    }

    ...
}

@RunWith(CdiRunner.class)
public class ApplicationServiceTest {

    @Produces
    @ProducesAlternative
    @Mock
    ApplicationManager manager;

    @Inject
    ApplicationService service;

    @Test
    public void testGetApplicationsListCalled() {
        service.getApplicationsList();
        verify(manager, times(1)).getApplications();
    }

    @Test
    public void testGetApplicationsListPassthrough() {
        ArrayList<Application> given = new ArrayList<>();
        given.add(new Application("app1", "desc1", BusinessCriticality.C1));
        given.add(new Application("app2", "desc2", BusinessCriticality.C1));
        when(manager.getApplications()).thenReturn(given);

        List<Application> resulting = service.getApplicationsList();

        Assert.assertEquals(given, resulting);
        Assert.assertEquals(2, resulting.size());
    }
}

I'd love to hear opinions from experienced devs on whether testing such methods makes sense and if it does, which method of testing is better.



Answers 3


From best practices perspective keep unit tests (JUnits + mock) separate from integration tests. You want unit tests to run independent of any system resources (barring any test data resource files). You can either mock service.getApplicationsList() or implement a factory pattern that will return service.getApplicationListFromTestImpl() in your first method to work with test data.

Integration tests should cover all system resources.

donlys
donlys
October 31, 2016 18:00 PM

You have to distiguish between whitebox tests and blackbox tests.

As blackbox tests do not know, how a component behaves, you have no clue if the called method is only a delegate or complex logic. As well you abstract from knowing which resources will be accessed so any potential resource has to be available a test runtime (unless you know to mock some resources). As you do not know a lot of things, you have assume the worst. So you should test every method. Black box test tend to be integration tests.

As the code provided is code under your control you know what the code is doing whitebox tests are appropriate. So you know if a method is only a delegate. These methods should not be tested as these tests express nothing. What you should do is to test if the object which methods are delegated to is properly initialized (null reference exceptions). If you now test the method of the delegate-object you are done because you know delegation can be process as the object is available and the delegated method works fine.

Unit tests for a method begin with at least TWO statements as with a second statement you maybe introduce first interesting thing to test: call order.

The next structure you should be aware of are conditional statements. You should try to refactor methods to have only one level of conditions. The problem with conditions is they may lead to a test case explosion if you have too much levels and conditional elements. Beside test possibility: To have small methods is always a good idea.

oopexpert
oopexpert
October 31, 2016 20:03 PM

Adding to oopexpert's answer. White boxing testing for facades can have tests for error handling also. Tests to make sure that the facade is handling all the exception that can be thrown by the service client.

IThinkSo
IThinkSo
October 16, 2017 10:19 AM

Related Questions


Integration tests, but how much?

Updated February 28, 2017 08:05 AM

What does stubbing mean in programming?

Updated March 03, 2017 13:05 PM

i want a postman's counterpart for mobile developers

Updated December 05, 2017 07:05 AM