简体   繁体   中英

Testing a method which calls another method

I have a method in my service layer:

  public List<String> sortBarcodesByTotalPrice(Set<String> barcodesByBookType) {
        List<String> toSort = new ArrayList<>();
        for (String barcode : barcodesByBookType) {
[1]         String combined = barcode + "/" + priceOperations.calculatePriceByBarcode(barcode);
            toSort.add(combined);
        }
[2]     toSort.sort(new TotalPriceComparator());
        return toSort;
    }

[1] this line gets barcode, lets say "ABC" and then calls a method in another class which retrieves information from the database about that item, performs calculation and returns the price. The possible combined value could be something like "ABC/10" .

[2] sorts all the values by price, ascending. So if List contains and "DEF/15" and "ABC/10" it gets sorted to [0] = "ABC/10" , [1]= "DEF/15" .

When I try to test this method, I get null pointer exception when priceOperations.calculatePRiceByBarcode(barode) gets called. How do I test this method? I've tried searching and found some questions and answers about using mockito but I can't figure out how to implement this.

my current attempt at testing this method:

    @Test
    void sortBarcodesByTotalPrice() {
        Set<String> toSort = new HashSet<>();
        toSort.add("ABC/10");
        toSort.add("DEF/5");
        toSort.add("GHI/15");
        List<String> sorted = bookService.sortBarcodesByTotalPrice(toSort);
        assertEquals(sorted.get(0), "GHI");
        assertEquals(sorted.get(1), "ABC");
        assertEquals(sorted.get(2), "DEF");
    }

EDIT, SOLUTION: I have figured out how to solve this thanks to information from Kaj Hejer . This is my new test method, passing and working as intended, if I understand this correctly:

@Test
    void sortBarcodesByTotalPrice() {

        PriceOperations priceOperations = Mockito.mock(PriceOperations.class);

        Set<String> toSort = new HashSet<>();
        toSort.add("GHI");
        toSort.add("ABC");
        toSort.add("DEF");

        when(priceOperations.calculatePriceByBarcode("GHI")).thenReturn(new BigDecimal("15"));
        when(priceOperations.calculatePriceByBarcode("ABC")).thenReturn(new BigDecimal("10"));
        when(priceOperations.calculatePriceByBarcode("DEF")).thenReturn(new BigDecimal("5"));

        BookService bookService = new BookService(null, null, priceOperations);

        List<String> sorted = bookService.sortBarcodesByTotalPrice(toSort);
        assertEquals(sorted.get(0), "DEF/5");
        assertEquals(sorted.get(1), "ABC/10");
        assertEquals(sorted.get(2), "GHI/15");
    }

First you have to decide what to test where. You might want to have separate tests for BookService and for the PriceOperations class. Now your test are tesing both these classes.

If you want to write a test for the BookService class you can mock the PriceOperations class.

List<String> sorted = new ArrayList<>();
sorted.add("GHI");
sorted.add("ABC");
sorted.add("DEF");

PriceOperations priceOperations = Mockito.mock(PriceOperations.class);
when(priceOperations. calculatePriceByBarcode(Mockito.<String>anyList())).thenReturn(sorted);

When injecting the PriceOperations into the BookService constructor injection is a smart way of injecting because it make it easier to write tests. Then you can inject the mocked priceOperations with

BookService bookService = new BookService(priceOperations);

Please let me know if this is useful!

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