Fake objects help test code by pretending to be real parts. They let us check how code works without using real systems.
Fake objects in JUnit
class FakeService implements ServiceInterface { @Override public String getData() { return "fake data"; } }
Fake objects are simple classes that implement the same interface as the real object.
They return fixed or controlled data to help test specific scenarios.
import java.util.HashMap; import java.util.Map; class FakeDatabase implements Database { private Map<String, String> data = new HashMap<>(); @Override public String fetch(String key) { return data.getOrDefault(key, "default"); } public void addData(String key, String value) { data.put(key, value); } }
import java.util.ArrayList; import java.util.List; class FakeEmailSender implements EmailSender { private List<String> sentEmails = new ArrayList<>(); @Override public void send(String email) { sentEmails.add(email); } public List<String> getSentEmails() { return sentEmails; } }
This test uses a fake service to check that the client gets the expected data. It does not use any real service.
import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; import java.util.*; interface Service { String getData(); } class FakeService implements Service { @Override public String getData() { return "fake data"; } } class Client { private Service service; public Client(Service service) { this.service = service; } public String fetchData() { return service.getData(); } } public class FakeObjectTest { @Test public void testFetchDataWithFake() { Service fakeService = new FakeService(); Client client = new Client(fakeService); String result = client.fetchData(); assertEquals("fake data", result); } }
Fake objects are simpler than mocks or stubs and usually have working code.
Use fakes when you want a lightweight replacement that behaves like the real object.
Keep fake objects easy to understand and maintain.
Fake objects replace real parts with simple versions for testing.
They help test code without slow or unavailable dependencies.
Fakes implement the same interface and return controlled data.
Practice
fake object in JUnit testing?Solution
Step 1: Understand the role of fake objects
Fake objects are simplified versions of real components used in tests to isolate the code under test.Step 2: Identify the main purpose
The main purpose is to replace real parts that might be slow, unavailable, or unpredictable with controlled versions.Final Answer:
To replace a real component with a simple version for controlled testing -> Option AQuick Check:
Fake objects replace real parts for testing [OK]
- Confusing fake objects with mocks or stubs
- Thinking fake objects generate random data
- Assuming fake objects speed up compilation
DataService?Solution
Step 1: Recall Java syntax for implementing interfaces
In Java, a class implements an interface using theimplementskeyword and must provide method implementations.Step 2: Check each option
public class FakeDataService implements DataService { public int getData() { return 42; } } correctly usesimplementsand defines the method. public class FakeDataService extends DataService { public int getData() { return 42; } } incorrectly usesextendswith an interface. public interface FakeDataService implements DataService { int getData(); } wrongly declares an interface implementing another interface with method body. public class FakeDataService { int getData() { return 42; } } lacks interface implementation.Final Answer:
public class FakeDataService implements DataService { public int getData() { return 42; } } -> Option CQuick Check:
Class implements interface with 'implements' keyword [OK]
- Using 'extends' instead of 'implements' for interfaces
- Defining interface instead of class for fake
- Omitting method implementation in fake class
interface Calculator { int add(int a, int b); }
class FakeCalculator implements Calculator {
public int add(int a, int b) { return 10; }
}
@Test
void testAdd() {
Calculator calc = new FakeCalculator();
assertEquals(10, calc.add(3, 7));
}Solution
Step 1: Analyze the fake object's method
Theaddmethod inFakeCalculatoralways returns 10 regardless of inputs.Step 2: Check the assertion in the test
The test asserts thatcalc.add(3, 7)equals 10, which matches the fake's return value.Final Answer:
Test passes because fake returns fixed 10 -> Option DQuick Check:
Fake returns fixed value matching assertion [OK]
- Expecting real addition instead of fake's fixed return
- Confusing compilation errors with missing annotations
- Assuming runtime exceptions without cause
interface UserRepository {
String findUserName(int id);
}
class FakeUserRepository implements UserRepository {
public String findUserName() {
return "TestUser";
}
}Solution
Step 1: Compare method signatures
The interface methodfindUserNamerequires anint idparameter, but the fake method has no parameters.Step 2: Understand Java interface implementation rules
Implementing classes must match method signatures exactly, including parameters.Final Answer:
Method signature does not match interface method -> Option AQuick Check:
Method signatures must match interface exactly [OK]
- Ignoring method parameters in fake implementation
- Thinking return type mismatch is the error
- Believing class must be abstract to implement interface
Solution
Step 1: Identify the problem with the real API
The real API is slow and unreliable for tests, causing delays and flakiness.Step 2: Choose a fake object approach
Creating a fake client that implements the same interface and returns fixed data instantly isolates the service and speeds tests.Step 3: Evaluate other options
Use the real API client but add delays in the test to wait for responses slows tests further. Mock the API client to throw exceptions randomly during tests adds randomness, reducing reliability. Remove the API client dependency from the service code breaks service functionality.Final Answer:
Create a fake API client implementing the same interface that returns fixed test data instantly -> Option BQuick Check:
Fake replaces slow API with fast fixed data [OK]
- Adding delays instead of faking slow parts
- Using mocks to add randomness in tests
- Removing dependencies instead of faking them
Ready to prove it?
Pass the test and this pattern moves unknown
