BAWABAA
No Result
View All Result
  • Home
  • Products
  • Services
    • Courses
    • Pathways
  • Solutions
  • Plans
  • Resources
    • List of Curated Edtech Websites
    • Pathways
    • Blog
      • Programming Languages
      • Tech
      • Graphic Design
      • Inspiration
      • Software Testing
      • Operating Systems
      • Frameworks
BAWABAA
  • Home
  • Products
  • Services
    • Courses
    • Pathways
  • Solutions
  • Plans
  • Resources
    • List of Curated Edtech Websites
    • Pathways
    • Blog
      • Programming Languages
      • Tech
      • Graphic Design
      • Inspiration
      • Software Testing
      • Operating Systems
      • Frameworks
No Result
View All Result
BAWABAA
No Result
View All Result
Home Frameworks

Unit Testing with Dummy Object in Test Doubles

January 31, 2025
Reading Time: 13 mins read

Here’s another example using a dummy object, this time in the context of an online shopping cart system.


Context: Shopping Cart System

In an online shopping cart system, a CartService class manages the cart. It depends on a DiscountService to calculate discounts on items. However, some methods in CartService, like calculating the total cost without discounts, do not require the DiscountService.


Classes:

DiscountService:

An interface for calculating discounts.

public interface DiscountService {
    double applyDiscount(double totalCost);
}

CartService:

This class manages the shopping cart and uses the DiscountService to apply discounts. However, some methods, such as calculating the total cost of items without discounts, do not require DiscountService.

import java.util.HashMap;
import java.util.Map;

public class CartService {

    private DiscountService discountService;
    private Map<String, Double> cartItems; // Stores item names and their prices

    public CartService(DiscountService discountService) {
        this.discountService = discountService;
        this.cartItems = new HashMap<>();
    }

    // Add an item to the cart
    public void addItem(String itemName, double price) {
        cartItems.put(itemName, price);
    }

    // Calculate the total cost of items without discounts
    public double calculateTotalCost() {
        return cartItems.values().stream().mapToDouble(Double::doubleValue).sum();
    }
}

Dummy Implementation:

The dummy DiscountService is created just to satisfy the dependency in the CartService constructor.

// Dummy implementation of DiscountService
public class DummyDiscountService implements DiscountService {
    @Override
    public double applyDiscount(double totalCost) {
        // No implementation needed for this dummy
        return totalCost;
    }
}

Unit Test:

We will test the calculateTotalCost method, which does not depend on the DiscountService.

import org.junit.Test;
import static org.junit.Assert.*;

public class CartServiceTest {

    @Test
    public void testCalculateTotalCost() {
        // Create a dummy discount service
        DiscountService dummyDiscountService = new DummyDiscountService();

        // Create the CartService instance with the dummy discount service
        CartService cartService = new CartService(dummyDiscountService);

        // Add items to the cart
        cartService.addItem("Item1", 10.0);
        cartService.addItem("Item2", 20.0);
        cartService.addItem("Item3", 30.0);

        // Calculate total cost without any discounts
        double totalCost = cartService.calculateTotalCost();
        assertEquals(60.0, totalCost, 0.01); // Verify the total cost
    }
}

Key Points of This Example:

  1. Dummy Object:
    • The DummyDiscountService is used solely to satisfy the dependency required by the CartService constructor.
    • It has no behavior or logic because it is irrelevant for the method being tested.
  2. Test Focus:
    • The test focuses only on the calculateTotalCost method, which does not depend on DiscountService.
  3. Simplified Setup:
    • By using a dummy object, the test avoids unnecessary complexity, such as mocking or stubbing DiscountService.

Why It’s a Dummy and Not a Stub:

  • The DummyDiscountService is not used during the test and provides no behavior.
  • It exists purely to satisfy the constructor dependency of CartService.

This example demonstrates how dummy objects can be used in an e-commerce shopping cart system!

Here’s another example using a dummy object, this time in the context of a restaurant reservation system.


Context: Restaurant Reservation System

In a restaurant reservation system, a ReservationService class manages reservations. It depends on a NotificationService to send confirmation messages to customers. However, some methods in ReservationService, such as checking table availability, do not require the NotificationService.


Classes:

NotificationService:

An interface for sending notifications to customers.

public interface NotificationService {
    void sendNotification(String customerName, String message);
}

ReservationService:

This class manages reservations and sends notifications for confirmations. However, some methods, like checking table availability, do not depend on NotificationService.

import java.util.HashMap;
import java.util.Map;

public class ReservationService {

    private NotificationService notificationService;
    private Map<Integer, Boolean> tableAvailability; // Maps table numbers to availability status

    public ReservationService(NotificationService notificationService) {
        this.notificationService = notificationService;
        this.tableAvailability = new HashMap<>();
        for (int i = 1; i <= 10; i++) { // Assume 10 tables
            tableAvailability.put(i, true); // All tables are initially available
        }
    }

    // Check if a table is available
    public boolean isTableAvailable(int tableNumber) {
        return tableAvailability.getOrDefault(tableNumber, false);
    }

    // Reserve a table (not tested in this example)
    public void reserveTable(int tableNumber, String customerName) {
        if (isTableAvailable(tableNumber)) {
            tableAvailability.put(tableNumber, false); // Mark table as reserved
            notificationService.sendNotification(customerName, "Your table " + tableNumber + " has been reserved.");
        } else {
            throw new IllegalArgumentException("Table " + tableNumber + " is not available.");
        }
    }
}

Dummy Implementation:

The dummy NotificationService is created solely to satisfy the dependency in the ReservationService constructor.

// Dummy implementation of NotificationService
public class DummyNotificationService implements NotificationService {
    @Override
    public void sendNotification(String customerName, String message) {
        // No implementation needed for this dummy
    }
}

Unit Test:

We will test the isTableAvailable method, which does not depend on the NotificationService.

import org.junit.Test;
import static org.junit.Assert.*;

public class ReservationServiceTest {

    @Test
    public void testIsTableAvailable() {
        // Create a dummy notification service
        NotificationService dummyNotificationService = new DummyNotificationService();

        // Create the ReservationService instance with the dummy notification service
        ReservationService reservationService = new ReservationService(dummyNotificationService);

        // Check availability of some tables
        assertTrue(reservationService.isTableAvailable(1)); // Table 1 is available
        assertTrue(reservationService.isTableAvailable(10)); // Table 10 is available
        assertFalse(reservationService.isTableAvailable(11)); // Table 11 does not exist
    }
}

Key Points of This Example:

  1. Dummy Object:
    • The DummyNotificationService is used only to fulfill the dependency required by the ReservationService constructor.
    • It does not perform any operations during the test.
  2. Test Focus:
    • The test focuses solely on the isTableAvailable method, which does not involve the NotificationService.
  3. Simplified Setup:
    • The dummy object removes the need for a fully functional or mocked NotificationService, making the test simpler and focused.

Why It’s a Dummy and Not a Stub:

  • The DummyNotificationService does not provide any behavior and is not invoked during the test.
  • It exists purely to satisfy the constructor dependency of ReservationService.

This example demonstrates a dummy object in a restaurant reservation system context, a scenario commonly seen in real-world applications!

Here’s another example using a dummy object, this time in the context of a file processing system.


Context: File Processing System

In a file processing system, a FileProcessor class reads and processes files. It depends on a Logger to log errors and informational messages. However, some methods, like counting the lines in a file, do not require the Logger.


Classes:

Logger:

An interface for logging messages.

public interface Logger {
    void logInfo(String message);
    void logError(String message);
}

FileProcessor:

This class processes files and uses the Logger for logging. However, some methods, such as counting the lines in a file, do not depend on the Logger.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class FileProcessor {

    private Logger logger;

    public FileProcessor(Logger logger) {
        this.logger = logger;
    }

    // Count the number of lines in a file
    public int countLines(String filePath) throws IOException {
        int lineCount = 0;
        try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
            while (reader.readLine() != null) {
                lineCount++;
            }
        }
        return lineCount;
    }

    // Process a file (not tested in this example)
    public void processFile(String filePath) {
        try {
            logger.logInfo("Starting file processing: " + filePath);
            // Simulate file processing logic here
            logger.logInfo("File processed successfully: " + filePath);
        } catch (Exception e) {
            logger.logError("Error processing file: " + filePath);
        }
    }
}

Dummy Implementation:

The dummy Logger is created solely to satisfy the dependency in the FileProcessor constructor.

// Dummy implementation of Logger
public class DummyLogger implements Logger {
    @Override
    public void logInfo(String message) {
        // No implementation needed for this dummy
    }

    @Override
    public void logError(String message) {
        // No implementation needed for this dummy
    }
}

Unit Test:

We will test the countLines method, which does not depend on the Logger.

import org.junit.Test;
import static org.junit.Assert.*;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class FileProcessorTest {

    @Test
    public void testCountLines() throws IOException {
        // Create a temporary file
        Path tempFile = Files.createTempFile("testFile", ".txt");
        try (FileWriter writer = new FileWriter(tempFile.toFile())) {
            writer.write("Line 1\n");
            writer.write("Line 2\n");
            writer.write("Line 3\n");
        }

        // Create a dummy logger
        Logger dummyLogger = new DummyLogger();

        // Create the FileProcessor instance with the dummy logger
        FileProcessor fileProcessor = new FileProcessor(dummyLogger);

        // Test the countLines method
        int lineCount = fileProcessor.countLines(tempFile.toString());
        assertEquals(3, lineCount);

        // Clean up the temporary file
        Files.delete(tempFile);
    }
}

Key Points of This Example:

  1. Dummy Object:
    • The DummyLogger is used solely to satisfy the dependency required by the FileProcessor constructor.
    • It is not used in the countLines method being tested.
  2. Test Focus:
    • The test focuses on the countLines method, which performs file operations but does not depend on logging.
  3. Temporary File:
    • A temporary file is created for testing, ensuring no dependencies on specific file paths or pre-existing files.
  4. Simplified Setup:
    • Using a dummy object avoids implementing or mocking Logger, making the test focused and concise.

Why It’s a Dummy and Not a Stub:

  • The DummyLogger is not called during the test and provides no behavior.
  • It exists purely to fulfill the constructor dependency of FileProcessor.

This example illustrates how dummy objects can be applied in a file processing system!

Here’s another example using a dummy object, this time in the context of a payment processing system.


Context: Payment Processing System

In a payment processing system, a PaymentProcessor class handles payment transactions. It depends on an AuditService to log audit trails for every transaction. However, some methods, like calculating total transaction amount, do not require the AuditService.


Classes:

AuditService:

An interface for auditing payment transactions.

public interface AuditService {
    void logTransaction(String transactionId, String message);
}

PaymentProcessor:

This class processes payments and uses the AuditService for transaction auditing. Some methods, like calculating the total transaction amount, do not depend on AuditService.

import java.util.ArrayList;
import java.util.List;

public class PaymentProcessor {

    private AuditService auditService;
    private List<Transaction> transactions;

    public PaymentProcessor(AuditService auditService) {
        this.auditService = auditService;
        this.transactions = new ArrayList<>();
    }

    // Represents a payment transaction
    public static class Transaction {
        private String transactionId;
        private double amount;

        public Transaction(String transactionId, double amount) {
            this.transactionId = transactionId;
            this.amount = amount;
        }

        public String getTransactionId() {
            return transactionId;
        }

        public double getAmount() {
            return amount;
        }
    }

    // Add a transaction
    public void addTransaction(Transaction transaction) {
        transactions.add(transaction);
    }

    // Calculate the total amount of all transactions
    public double calculateTotalAmount() {
        return transactions.stream().mapToDouble(Transaction::getAmount).sum();
    }

    // Process a transaction (not tested in this example)
    public void processTransaction(Transaction transaction) {
        auditService.logTransaction(transaction.getTransactionId(), "Transaction processed: $" + transaction.getAmount());
    }
}

Dummy Implementation:

The dummy AuditService is created solely to satisfy the dependency in the PaymentProcessor constructor.

// Dummy implementation of AuditService
public class DummyAuditService implements AuditService {
    @Override
    public void logTransaction(String transactionId, String message) {
        // No implementation needed for this dummy
    }
}

Unit Test:

We will test the calculateTotalAmount method, which does not depend on the AuditService.

import org.junit.Test;
import static org.junit.Assert.*;

public class PaymentProcessorTest {

    @Test
    public void testCalculateTotalAmount() {
        // Create a dummy audit service
        AuditService dummyAuditService = new DummyAuditService();

        // Create the PaymentProcessor instance with the dummy audit service
        PaymentProcessor paymentProcessor = new PaymentProcessor(dummyAuditService);

        // Add transactions
        paymentProcessor.addTransaction(new PaymentProcessor.Transaction("T001", 100.0));
        paymentProcessor.addTransaction(new PaymentProcessor.Transaction("T002", 200.0));
        paymentProcessor.addTransaction(new PaymentProcessor.Transaction("T003", 300.0));

        // Calculate the total amount
        double totalAmount = paymentProcessor.calculateTotalAmount();

        // Verify the total amount
        assertEquals(600.0, totalAmount, 0.01);
    }
}

Key Points of This Example:

  1. Dummy Object:
    • The DummyAuditService is used solely to satisfy the dependency required by the PaymentProcessor constructor.
    • It has no behavior or logic because it is not required for the method being tested.
  2. Test Focus:
    • The test focuses only on the calculateTotalAmount method, which does not require any interaction with the AuditService.
  3. Simplified Setup:
    • By using a dummy object, the test avoids unnecessary complexity related to auditing.

Why It’s a Dummy and Not a Stub:

  • The DummyAuditService is not used during the test and provides no behavior.
  • It exists purely to fulfill the constructor dependency of PaymentProcessor.

This example demonstrates the use of a dummy object in a payment processing system while testing methods that don’t rely on external dependencies.

Share7Tweet4Share1
Previous Post

Dummy Object Test Doubles in Unit testing with Java and Mockito

Next Post

Stub Object in Unit testing with Java

Next Post

Stub Object in Unit testing with Java

Unit testing - Stub Object in Java

Unit Testing - Test Doubles: Dummy, Stub and Mock Examples

Soft skills Outlines

List of Curated Edtech Websites

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Categories

  • Frameworks (22)
  • Programming Languages (4)
  • Tech (1)

© 2025 Bawabaa.com

No Result
View All Result
  • Home
  • Products
  • Services
    • Courses
    • Pathways
  • Solutions
  • Plans
  • Resources
    • List of Curated Edtech Websites
    • Pathways
    • Blog
      • Programming Languages
      • Tech
      • Graphic Design
      • Inspiration
      • Software Testing
      • Operating Systems
      • Frameworks

© 2025 Bawabaa.com