Junit Tests pass individually but fail when run together

Viewed 2314

I'm currently working on an assignment for school and I'm struggling with the testing portion. For some reason the unit tests run fine when run individually but not when run together. I know this has something to do with me sharing the object between them when I shouldn't be based on my prior searches, but I can not for the life of me figure out what needs to be changed to remedy this problem. The code is below for both the AppointmentService class as well as the AppointmentServiceTest class. Any help would be greatly appreciated as I've been stuck on this for some time now and know it's probably something that someone else will see immediately.

The AppointmentServiceTest class


import static org.junit.jupiter.api.Assertions.*;

import java.text.ParseException;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import main.Appointment;
import main.AppointmentService;

class AppointmentServiceTest {

    private static AppointmentService appointmentService;
    
    @BeforeAll
    static void setUp() {
        appointmentService = AppointmentService.getService();
    }
    
    @Test
    void testAddAppointmentSuccess() throws ParseException {
        Appointment appointment = new Appointment("123456", "2022-10-01", "Appointment Description String");
        assertTrue(appointmentService.addAppointment(appointment));
        
        Appointment cachedAppointment = appointmentService.getAppointment(appointment.getAppointmentId());
        
        assertTrue(cachedAppointment != null);
        assertTrue(cachedAppointment.getAppointmentId().equals("123456"));
        assertTrue(cachedAppointment.getAppointmentDate().equals("2022-10-01"));
        assertTrue(cachedAppointment.getAppointmentDescription().equals("Appointment Description String")); 
    }
    
    @Test
    void testAddMultipleAppointmentsSuccess() throws ParseException {
        Appointment appointment1 = new Appointment("123456", "2022-10-01", "Appointment Description String");
        Appointment appointment2 = new Appointment("1234567", "2022-10-02", "Appointment Description String2");
        
        assertTrue(appointmentService.addAppointment(appointment1));
        Appointment cachedAppointment1 = appointmentService.getAppointment(appointment1.getAppointmentId());
        
        assertTrue(cachedAppointment1 != null);
        assertTrue(cachedAppointment1.getAppointmentId().equals("123456"));
        assertTrue(cachedAppointment1.getAppointmentDate().equals("2022-10-01"));
        assertTrue(cachedAppointment1.getAppointmentDescription().equals("Appointment Description String"));    
        
        assertTrue(appointmentService.addAppointment(appointment2));
        Appointment cachedAppointment2 = appointmentService.getAppointment(appointment1.getAppointmentId());
        
        assertTrue(cachedAppointment2 != null);
        assertTrue(cachedAppointment2.getAppointmentId().equals("1234567"));
        assertTrue(cachedAppointment2.getAppointmentDate().equals("2022-10-02"));
        assertTrue(cachedAppointment2.getAppointmentDescription().equals("Appointment Description String2"));
        
    }
    
    @Test
    void testAddAppoitnmentDuplicateIdFail() throws ParseException {
        Appointment appointment1 = new Appointment("123456", "2022-10-01", "Appointment Description String");
        Appointment appointment2 = new Appointment("123456", "2022-10-01", "Appointment Description String");


        assertTrue(appointmentService.addAppointment(appointment1));
        assertFalse(appointmentService.addAppointment(appointment2));
    }
    
    @Test
    void testGetAppointmentAndUpdateSuccess() throws ParseException {
        Appointment appointment = new Appointment("123456", "2022-10-01", "Appointment Description String");
        assertTrue(appointmentService.addAppointment(appointment));
        
        Appointment updatedAppointment = appointmentService.getAppointment(appointment.getAppointmentId());
        updatedAppointment.setAppointmentDate("2022-10-02");
        updatedAppointment.setAppointmentDescription("New Description");
        
        updatedAppointment = appointmentService.getAppointment(updatedAppointment.getAppointmentId());
        
        assertTrue(updatedAppointment.getAppointmentDescription().equals("New Description"));
        assertTrue(updatedAppointment.getAppointmentDate().equals("2022-10-02"));
    }
    
    @Test
    void testGetAppointmentAndDeleteSuccess() throws ParseException {
        Appointment appointment = new Appointment("123456", "2022-10-01", "Appointment Description String");
        
        assertTrue(appointmentService.addAppointment(appointment));
        
        appointment = appointmentService.getAppointment(appointment.getAppointmentId());
        assertTrue(appointment != null);
        
        assertTrue(appointmentService.deleteAppointment(appointment.getAppointmentId()));
        assertTrue(appointmentService.getAppointment(appointment.getAppointmentId()) == null);
    }
    
    @Test
    void testDeleteInvalidAppointmentFail() {
        String invalidAppointmentIdString = "123";
        
        assertFalse(appointmentService.deleteAppointment(invalidAppointmentIdString));
    }

And the AppointmentService Class


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

public class AppointmentService {

    private static AppointmentService reference = new AppointmentService();
    private final Map<String, Appointment> appointmentList;
    
    AppointmentService() {
        this.appointmentList = new HashMap<String, Appointment>();
    }
    
    public static AppointmentService getService() {
        return reference;
    }
    
    public boolean addAppointment(Appointment appointment) {
        boolean isSuccess = false;
        
        if(!appointmentList.containsKey(appointment.getAppointmentId())) {
            appointmentList.put(appointment.getAppointmentId(), appointment);
            isSuccess = true;
        }
        return isSuccess;
    }
    
    public boolean deleteAppointment(String appointmentId) {
        return appointmentList.remove(appointmentId) != null;
    }
    
    public Appointment getAppointment(String appointmentId) {
        return appointmentList.get(appointmentId);
    }
    
}


 
2 Answers

You are using same appointmentService instance for your 2 test and adding the appointment with same id ("123456") in your 2 test. So, when tests are ran together, you next test will always fail as you are assuming that the id "123456" is not present in second test, but it is.

You should create a new appointmentService for each test as unit test = test in isolation, especially when your testing instance has some states.

Remove static in here

private static AppointmentService appointmentService;\

And fot setUp method too. Also change @BeforeAll to @BeforeEach it will make create new appointmentService for each test to isolate test cases.

Also if there is no any reason to have reference as static then class itself it's better to refactor (get rid of static reference) self-made singleton is kind of anti-pattern. Now when code calls getReference it returns always the same instance, that's why it does not work while running all tests.

See also https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html I hope it helps

Related