When you can’t or won’t make it, Fake it.

1. Faking as a testing technique.

Let’s revisit the movie making metaphor. We know that almost everything in that industry is fake, or maybe more politely make-belief. In that it only needs to look convincing without being the real thing. So for instance, when someone needs to be hit hard in the face, it will not really be done and to make sure nothing untoward happens to the expensive actors, they may be replaced by stunt men and women, so the punch will never land on the pretty face.

In our industry we have other reasons to not use the real thing.

  • It is not available (yet).

  • It is expensive (as in slow) to use and we want our tests to be quick.

  • We want to test behavior under circumstances that are rare, and difficult to achieve with the real thing.

  • It is inconvenient to use.

What we do is replace the Dependent On Components by so called mocks.
In all cases, the System Under Test, the class we are testing is always used as is. So we have no stunt doubles for our protagonist. When testing, we want it to take all the punches, because we want to make sure it can handle them.

A very common mistake made when using mocking as a testing technique, is faking the protagonist or SUT. This is very wrong. What you are testing in that case is the mock, not the class you hope to test. None of the code of the SUT will be used in such tests.

fitness
Figure 1. Never imagined coding as a work out.

Suppose you have an application in which one of the required effects is that a business class prints something to a printer. Turning this into a test will give you a hard time, because you have to run between your desk an printer, but hey, it will improve your fitness.[1].

To verify that the system under test (SUT) does indeed use the printer, make that fact observable, so that you can verify that the printer call has been made. You can use a trick common to many informatics problems and is available to you too: add a level of indirection, or do not give the actual printer to the business class but instead something that the business code thinks it is a printer and replace that with whatever suits you for the test.

annoyed 32 'Nice' you say, now I have two problems':

  1. change the application and

  2. create a printer just for my tests.

1.1. Stay cool, have a Mockito.

mockito drink
Figure 2. it gets better.

You are not the first developer in this situation, so someone has automated the creation of 'fake' objects or mocks for us:
Mockito is a framework that can create various objects that are useful for testing.

Mock is an object that behave like a (alternate) implementation of a class or interface. This is akin to an actor (or actress) or stunt-double that behaves exactly like you tell it to. A mock also saves any method call that you do on it.
Stub just holds data that you provide and are presented to the SUT.
Both mock and stub are stand-ins for dependent on components (DOC) or collaborators for the SUT.
There is also a
Spy which is in fact a wrapper around an actual implementation, that allows you to observe what goes in (method call+ parameters) and comes out of (return values) of the real object while it is used by the SUT. You can make the spy only spy on certain method calls, and leave the rest unchanged.

mockstubsspies
Figure 3. Class diagram explaining mocks, stubs and spies

Lets see what this looks like in code.

The printer interface.
public interface Printer {

    void println( String print );

    /**
     * Make it deal with objects too.
     * @param o to print.
     */
    default void println( Object o ) {
        printLn( o.toString() );
    }
}

Now over to the test class, which creates a mocked printer and hands it to the Business class.

Business test class.
    @Test
    public void doesItPrint() {
        Printer pr = mock( Printer.class );  (1)

        Business b = new Business( pr );     (2)

        b.work();                                 (3)

        verify( pr ).println( anyString() ); (4)

    }
1 Create the mocked printer.
2 Create a Business object passing it the printer.
3 Make the business class work.
4 ask the mocked printer if it was used.

This is of course a simple test and the only thing that it verifies is that the printer.printLn(String) has been used.

Verify that what is printed is okay.
    @Mock
    Printer printer; (1)

    Business business;

    @BeforeEach
    void setup() {
        business = new Business( printer );  (2)
    }

    @Test
    void doesItPrintBusiness() {
        ArgumentCaptor<String> lineCaptor = ArgumentCaptor.forClass( String.class ); (3)

        business.work( "Linda" ); (4)

        verify( printer ).println( lineCaptor.capture() ); (5)
        assertThat( lineCaptor.getAllValues() ).contains( "Hello Linda" ); (6)
        fail("test does It print ended. You know what to do.");
1 Setup mock as field
2 and business in a setup method, so tests can avoid repeating this,
again passing the printer object via the business constructor.
3 Prepare a mockito helper object to capture the data passed to the printer.
4 Make business do it’s thing.
5 Verify that printer.println(…​) is called. The captor object is used to collect all that has been received by the printer’s printLn method.
6 And the expected data is passed to the printer, so a real printer would print it. The method lineCaptor.getAllValues() produces a List of the captured things, strings in this case.

Mockito is well documented with lots of examples in its java doc. When you look to the test dependencies of your Maven project in NetBeans-IDE, right-click on the mockito dependency, then download the javadoc, you can enjoy that while you are developing. During a performance assessment the Javadoc should have been pre-loaded so is available in the same way.

1.2. To Mock or To Configure

Sometimes the class that you want to pass as a mock to the business code has a big interface, with many methods, and you do not want to restrict the business code to just a few trained methods. That would constrain the methods the business class could use, and that serves no real purpose. In such cases it may be better to provide a differently configured real class.

1.2.1. Input stubbing with a real,class.

An object that contains preconfigured data is called a Stub.
As an example: Assume you business class uses a Scanner as it’s input. Scanner has 50-odd methods, which you certainly do not want to train all when mocking.

But since you will pass a special Scanner to the business class anyway, the better way is to use a Scanner configured with one of it’s constructors. In this case use new Scanner( String s ), in which the string s contains exactly the input you want to use in your test. The string can contain newlines, so that it appears as if the user entered multiple lines. This allows you to test a program with a dialog. Something along the line of new Scanner("12\n13\n");, that is 12 newline 13.

1.2.2. Output mocking with a real classes

For the output side something similar is in effect. The most common way of outputting something is to use System.out to print or otherwise output the results of the program. But System.out is just a PrintStream, which also has a lot of convenience methods with a total of 33 methods and 10 constructors. You do not want to restrict the use of any of its methods in the business class.

The trick here is to use one of the constructors to given PrintStream something to 'print on', which you can inspect afterwards. Usage: The business class has a constructor.[2] or setter to take a PrintStream and always uses that to print to, if it needs to print anyway.

Usage is business code
public class PrintingBusiness
      final PrintStream out; (1)

      public PrintingBusiness() { (2)
          this( System.out );
      }

      PrintingBusiness( PrintStream ps ) { (3)
          this.out=ps;
      }

      public void businessMethod(){
          out.format( "%s at %d", "Oplegkaas", 957 ); (4)
      }
}
1 final to have a constructor set it
2 Default constructor (using the other constructor) uses System.out to print to
3 Redirect output to other output, for test or 'printing' in a GUI.
4 All facilities of PrintStream are available, including formatted printing.
Use in tests
    @Test
    public void tformattedPrint() {
        ConsoleOutput cout = new ConsoleOutput();
        PrintStream out = cout.asPrintStream();

        out.format( "%s at %d", "Oplegkaas", 957 );

        assertThat( cout.toString() ).contains( "at", "Oplegkaas", "957" );
    }

By implementing the AppendAndClear interface you can print to anything, for instance by using a StringBuilder as intermediate and then transfer the output to a GUI element in JavaFX or Swing.

Definition of AppendAndClear interface.
@FunctionalInterface
public interface AppendAndClear {

    /**
     * Append a string to this AppendAndClear.
     *
     * @param toAppend text to add.
     */
    void appendText( String toAppend );

    /**
     * Clear the output. Optional operation.
     */
    default void clear() {
    }
}
Implementation of ConsoleOutput
package consoleoutput;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * Test helper, to be able to redirect a PrintStream to any writable.
 *
 * Use case: write to string or StringBuilder for test or e.g. javafx
 * TextInputControl for UI. Implement AppendAndClear (which can be done as a
 * lambda) and you're set.
 *
 * @author Pieter van den Hombergh {@code <p.vandenhombergh@fontys.nl>}
 */
public class ConsoleOutput extends OutputStream {

    protected final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    final AppendAndClear aac;

    /**
     * Create a Console output copying data to given AppendAndClear.
     *
     * @param ta append and clear to copy all written text to.
     */
    public ConsoleOutput( AppendAndClear ta ) {
        this.aac = ta;
    }

    /**
     * Without appendable.
     */
    public ConsoleOutput() {
        this( null );
    }

    @Override
    public void write( int b ) throws IOException {
        if ( aac != null ) {
            String s = "" + ( (char) b );
            aac.appendText( s );
        }
        baos.write( (byte) b );
    }

    /**
     * Clear and discard output.
     */
    public void clear() {
        if ( aac != null ) {
            aac.clear();
        }
        baos.reset();
    }

    /**
     * Get the accumulated string since start or clear.
     *
     * @return the string
     */
    @Override
    public String toString() {
        return new String( baos.toByteArray(), StandardCharsets.UTF_8 );
    }

    /**
     * Factory method to get this ConsoleOutput as PrintStream.
     *
     * @return the print stream.
     */
    public PrintStream asPrintStream() {
        return new PrintStream( this, true, Charset.defaultCharset() );
    }
} // eof ConsoleOutput
You can redirect standard output and standard error this way

You can modify standard output, a.k.a. System.out so that it writes to somewhere else, for instance to something like the console output above. System.setOut(PrintStream) can be used for standard output. This is also the trick that the PRC1 MOOC used to test output by the first programs. Important is that it can also be applied to static methods such as the well known public static void main(String[]) that can’t be used with Dependency Inversion as we do here.

Real class configuration, if applicable, beats mocking. So if there is an existing class, first study it’s API, before you consider mocking it. Using the Real Thing may be the better choice AND less work.
Along that line: It is seldom useful to mock an entity class, like a Student or Product, because the mock will have no benefit over the real thing, since the entity is just a data carrier with no logic. The typical shape of an entity is a constructor, a few getters and some other generated boilerplate code, such as toString(), equals(Object) and hashCode(). Java 14+ records will be a good substitute for such classes.

Exercise My First Mock

DOC Rhymes with mock

My First Mock

In this exercise, you will use your first mocks. To mock something is essentially to fake something. Mocking, or faking classes is a common way of testing code. For example if you test code that writes something to a database, you want to make sure that the writing of data works correctly. But setting up a database and connecting to it introduces LOTS of ways the code could fail, rendering your test meaningless. To circumvent this problem, you mock the database. You create a dummy object and say "this is my pretend database". In this exercise, you will mock something else: a Printer.

Let’s check out our myfirstmock project. We have a Printer interface with the methods void Println(String print) and int countCharactersPrinted();. The first method does the actual printing, the second method returns the count of the characters printed.[3]

Looking at the Business.java class, we see the code that makes use of the Printer interface. There is a void work(String input) method, which should print the input given to the method. Interesting is the double computePrintingCost(double price) method. With this method, the business class computers the cost of a print by multiplying the price with the number of characters printed.

As usual, we start with the Test class. Straight away, we see two fields in this test class: printer and business. The business is the System Under Test, also called a SUT. It’s the code that we want to test, i.e. the one we want to make sure is working. The business class however can’t do its work without implementing some form of printer. It depends on the printer. The printer is therefore the depended-on component, also called the DOC.

When testing, we mock the DOC and we verify that the SUT is working. The DOC will not be fully implemented- it will only be mocked, i.e. faked! We can see that the printer is mocked thanks to the annotation @Mock. The business class won’t be mocked, because we want to test it- you can’t test a fake object! But before you can test a class that uses a mocked object, we first need to train it. For example, if you mock a calculator, you don’t implement the add(int a, int b) method. Instead, you train it to return 2 when the input is 1 + 1. Check the pseudo-code below to see how to train mocked objects.

To help you, here is a series of commands that will be handy:
   when(mockedObject.methodOfObject()).thenReturn(something); (1)
   verify(someObject).methodOfObject();                       (2)
   assertThat(someCalculatedStuffFromBusinessObject)
       .isEqualTo(someValue); (3)
1 here we train the mocked object
2 verifies that the method of the mocked object was called
3 here we use our usual assert statement when we test the BUSINESS object (SUT), not the DOC!

Now to the exercise: write the three test methods provided and the implementation that it tests, TDD style. Start with the top test and work your way down. doesItPrint() only needs a verify, calculatePrintingCosts needs training, verification and assertion. The third test method, doesPrinterGetCorrectArgument(), is more complex. It makes use of the ArgumentCaptor. It basically is a catcher that captures (or catches) arguments that are passed to methods. In our example, our argument is a string, therefore we have a stringCaptor:

ArgumentCaptor<String> stringCaptor = ArgumentCaptor.forClass( String.class );

In your verify statement, you should pass the stringCaptor’s capture method. It allows the captor to catch the String that is sent to the business class to print. Then you assert that the stringCaptor’s values contain the String you are looking for. As usual, type the dot . after stringCaptor and see what options are available.

Use this myfirstmock project, after submitting the solution, to experiment with mocking. Experimenting is a first class activity for students!

2. Design for Test-ability

Also known as dependency injection made simple.

A very important non functional requirement of good software is Test-ability.
Test-ability can be achieved or improved by decoupling the class you are developing (the SUT) from it’s environment, such that you have full control over that environment in your test and can exactly control and observe what goes in or out of the SUT.

One first easy setup is to use package private visibility more often. It is actually the default in java, and with reason. When you then put your unit test in the same package (but it its own source tree), you can have the test class look at or use the package private members of the class in its assertion or verification very easily. Most of unit testing is white box testing anyway, which almost always includes inspecting private members.

For business code, organize your packages according to the collaborations the classes will have. In particular do NOT organize classes according to type or kind, like collections with collections and exceptions with exceptions. To express it as a metaphor: If you always keep your screws, seats, and backrests in separate boxes, they will never build chairs. You need to put them together, to make them cooperate.
For a library code, other aspects such as find-ability may take precedence over tight packages. But when you study the java libraries your will see classes in packages that are package private, to help the public types in the package to do their bidding.

Test-ability is also improved by using the design rule program against interfaces, not concrete classes.
If you do that in your design, you can very easily make specialized implementations of those interface methods that you need in your test, to provide those specific values or reactions that you need in your test, without having to jump through a lot of hoops to get the test set up.
This easy setup is where Mockito comes in.

It is not the business' business to worry about:
persistence
where service come from or who implements them.

By injecting or otherwise providing the business with the services it needs makes the business code testable without making it dependent or even know the actual implementing classes. And that is really all that counts. The business code makes the application valuable, the rest is either plumbing or already available code.[4].

Never let the business code create its own persistence or or service object. You would loose control over what flows between service and business class, and makes it unobservable, which is bad from the testing standpoint.

Instead hand the service or resource to the business, or give it some provider of a resource.

2.1. Business class fit for testing.

Let us look at an example as a class diagram.

testable business
Figure 4. Giving the business what it really needs make the business testable

For readers that like to watch still pictures:

businessarch
Figure 5. business class in the application
businesstest
Figure 6. business class in the test lab

In the picture above you see a class diagram which shows a detail in which a business class 'lives' in an environment that is designed to make sure the business class sticks to its business:

Dealing with business entities such as customers and products.
Uses services to do the business' bidding, such as saving stuff to a database, provided as a service to the business class.
And the business code NOT responsible for how to show things in a UI.

In the above example we provide a factory or provider of the services that the business code requires.

The business class appears in two worlds:

  1. A business world, the Application. This is the actual use and role in the whole application. In that world there is a so called Assembler, that stitches the parts of the application together and sets it on its way. Typically this Assembler role is what the main class in a project does. Find the parts, put them together, and put them to work.

  2. In the Test world, call it the laboratory or business.[5] school, where the business class is trained and tested. Here the test class does the assembling with a dash of Mockito to get good grips on what goes into and out of the business class.

Before the business class can used in real life, it has to be trained and tested. Feels a bit like a student right?

You should note the arrows in the diagram. They provide direction and make it the diagram a directed graph, and lets a dependent point to a depends-on, like the BusinessClass depends on a Service, which is an abstract class or better still, an interface. Also note that the service does not point to, or is dependent on the business, which is good, because it makes the service reusable in other contexts.
The service implementing classes are dependent on the Service definition which is shown with the inheritance arrow, pointing from sub to super type. In the example you could think of the service being a Data Access Object or DAO and the ServiceImpl a specific DAO, like DAO<Product>, or DAO<Customer>.

In the business school, there is a test class, that creates instances of the business class and hands it implementations of the services the business needs, but does that by giving it a specialized service factory that produces mock service implementations. The business class is NOT aware of that. It uses the service in the way it is programmed, which allows the test class to verify that that programming is correct. The test class is in complete control and can also give the business class situations that are extensions to the normal happy path to ensure that those situations are also handled properly. If that sounds like an exam setting at school, you would be right.

You can tell these worlds in the class diagrams apart by the fact that one has a pink BusinessTest class with test methods.

In the 'normal' non-testing Application world, the design has taken some provisions to make sure the business class can work in both worlds. To provide the business class with a factory from which it can obtain Service implementations, a so called Assembler is added. This Assembler, in the figure at the top of the application class diagram, typically creates or instantiates the business class and provides it with all it needs, in this case an implementation of a ServiceFactory. Note that the assembler in this case also creates the UI part. In desktop applications this is what the Main class of the application typically is for.

This approach of providing an instance of some class implementing an interface or realizing an abstract class to a business class that needs it is called dependency injection.

Dependency injection is providing the services required by some class by means of constructor parameters, setters or otherwise, to avoid that the dependencies of the class are created by that class itself.

The code in your tests also serve as a kind of documentation, at least for the maintainer of the test and code. This implies that any mock that you configure should match the test scenario, no more no less.
That’s why Mockito complains when you mock something or train a method, but do not use it in the test.

example Mockito Warning
Unnecessary stubbings detected.
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
1. -> at ps.CashRegisterTest.isProductLookedUpAndDisplayed(CashRegisterTest.java:71)
Please remove unnecessary stubbings or use 'lenient' strictness.
More info: javadoc for UnnecessaryStubbingException class.

When a mock is not used, and unverified, Mockito warns you about the fact. It might be an oversight on the side of the test or indeed a smell of a flaw in the business code. So take the Mockito warning seriously.

Exercise Testable Design

Perishable Products

Build part of a cash register system used in sales of products that might be perishable.

Class diagram

perishablesales

In the design we left out the GUI-controller, which would normally invoke the correctSalesPrice(bb: LocalDate), the submit(), and the print() methods on the cash register business component.

Perishable products are products with a limited shelf life. Think of fresh products such as milk, meat, vegetables, fruit, or anything that has a best before date.

Assume that all products are labeled with a bar-code which identifies the product and that a perishable product has a best before date or similar.

The cashier normally scans the product and that product is marked sold and optionally appears on the cash receipt.

A perishable product undergoes the same procedure, but in case the best before date is less than 2 days, the product should also be marked sold, but the the sales price should be 35% off. 0 days left 65% off, less than or equal 0 days left 100% off, no longer on sale but product will be donated to a food bank.

days left

percent off

remaining price in %

>= 2

0

100

1

35

65

0

65

35

< 0

100

0

The cash register uses the following service API

Sales API
   Product lookupProduct(int barcode);
   int salesPrice(int barcode, LocalDate bestBefore);
   String sold(SalesRecord sale);

As extra info: the SalesService.sold produces a string which is supposed to appear on the cash receipt and should therefore be printed using the Printer interface. Printing of all data is postponed until the cashier can ask: Do you want a receipt? The sold items should be ordered on the receipt as follows:

  • Perishable products should come first, non-perishables second.

  • The sold items should be printed in scan order.

    • If an item has been scanned multiple times, it should not be added to the list, but instead the count for the item should increase.

The CashRegister is given a clock and a SalesService at construction time. In dependency injection parlance this is called constructor injection for obvious reasons.
The clock is to be used to determine the actual date, the sales service to register to look up products and perform the sales registration. Both SalesService and Printer should be mocked for the purpose of testing.

Actual payment has been left out of this exercise.

Abbreviated Use Case Normal sale

As a cashier I want to scan a product, compute a sales record and submit the sales record when I scan the next product. This can keep me in a continuous flow of scanning products. Beep, Beep, Beep…​.

Abbreviated Use Case sale of Perishable Product

As a cashier I want to scan a perishable product and select the best before date that I can read on the label. When the product is perishable, I expect a calendar to be shown, in which I can select the best before date of the actual product. I have two alternatives:

  1. When I select a best before date on the presented calendar, the cash register should correct the price if applicable.

  2. When I select submit, the best before date is not considered.

When the operator did not select a best before date before she scans the next product, then the register should beep with a low tone and wait for me to comply.
This can be realised by having the cashregister throw an exception.

After either alternative the cash register should construct a sales record and submit it to the Sales Service. Then the cash register is ready for the next scan, or complete.

The low beep will be implemented by the Gui. To get this done throw an UnKnownBestBeforException.

  • In case of non-perishables, the accept(int) method can immediately use the sales service sold(SalesRecord) method.

  • In case of perishables, the cashregister operator must be show a calendar, and has two options, either

    1. accept the standard price by pressing the button that invokes the submit() method of the register, OR

    2. select a date from the calendar, so that the price correction can be computed by invoking correctSalesPrice(LocalDate).

  • Either of these methods should then use the sold(SalesRecord) in which the SalesRecord should have the correct price.

Abbriviated Use Case Print receipt

As a cashier I will ask the customer if he or she wants a receipt. If the answer is yes, I select print and the printer should print a receipt as specified above.

Your Tasks
Design your tests. You are supposed to use Mockito to mock the SalesService and Printer. Complete the class diagram with the things needed for testing and submit too. The updated class diagram is part of the exercise.

The Product and SalesRecord classes are given, complete with tests. There are no implementations for SalesServiceImpl and Printer yet, nor should they be created. Mock these services.

The mocked printer should be used to test that the information is printed in the specified order. In the implementation of the your CashRegister you can use a structure like a map of maps to organize the inputs. Choosing the proper map implementation is the trick here. Get inspired by the lava.util.Map API.

Test driven develop the Cash Register class.

It is sufficient to throw an exception when the perishable’s best before date is not selected. Beeping in a low tone can be done in a later version.

Hints in designing your tests:

  • First sell one product, to verify that printing contains all the relevant info for the product, quantity and price.

    • printReceipt and ask the mock what it received and inspect (verify, assert) that.

  • Then sell two of the same products (two scans, same barcode), non-perishable, to see if the count and price are correct. Same assertions, different values.

  • Then scan more products and ensure that the cash receipt contains the information as per requirement.

  • same approach with testing if the sales service is used properly. Here you do not need to keep the order.

  • The test method priceReductionNearBestBefore should probably be a @Parameterized test with a @CsvSource, in which you specify different best before days left.

    • You might also use a map to lookup products in a map, like "banana" will give you the defined banana product. Revisit part 02 on parameterized test where such usage is shown.

In this exercise you do not have to distinguish between different best before dates in the sales records for perishable. Assume that the tests only use one of each product type. This relevant business requirement might be included in a future version, that includes refactoring.

Exercises in this part


1. (source picture "https://www.menshealth.com/nl/fitness/")
2. best
3. Maybe page count or ink usage should be used, this is just an example
4. And hopefully tested
5. pun intended