Search code examples
javaspringjunitspring-boot-test

Junit tests fail due shared instances (i think)


I think my problem is related to this issue: Tests pass when run individually but not when the whole test class run

My tests all pass individually but when i run the test class, two of them fail. Debugging shows that that assertEquals is expecting different states than given in the code, mainly the states from different tests. The solution should be using a @Before or @After and do a cleanup, but i am having troubles using that becouse the instance is Autowired from Spring.

Main question: Is my thinking right and how do i 'reset' the autowired instance?

@SpringBootTest
class StatementProcessorServiceTest {

    @Autowired
    StatementProcessorService statementProcessorService;

    private StatementProcessorInputModel setup(long id, boolean endbalanceCorrect) {
        StatementProcessorInputModel statementProcessorInputModel = new StatementProcessorInputModel();
        statementProcessorInputModel.startBalance = 1.00;
        statementProcessorInputModel.id= id;
        statementProcessorInputModel.startBalance = 1.00;
        statementProcessorInputModel.mutation = 1.00;
        statementProcessorInputModel.endBalance = endbalanceCorrect ? 2.00 : 1.00;
        return statementProcessorInputModel;
    }

    @Test
    void verify_with_all_good_settings()
    {
        StatementProcessorResponseModel sut;
        sut = statementProcessorService.validate(setup(1, true));
        Assert.assertEquals(sut.result, "SUCCESSFUL");
    }

    @Test
    void verify_with_good_settings_but_duplicated_reference()
    {
        StatementProcessorResponseModel sutFirst = statementProcessorService.validate(setup(2, true));
        Assert.assertEquals(sutFirst.result, "SUCCESSFUL");
        StatementProcessorResponseModel sutSecond;
        sutSecond = statementProcessorService.validate(setup(2, true));
        Assert.assertEquals(sutSecond.result, "DUPLICATE_REFERENCE");
    }

    @Test
    void verify_with_wrong_endBalance_and_good_reference()
    {
        StatementProcessorResponseModel sut = statementProcessorService.validate(setup(3, false));
        Assert.assertEquals(sut.result, "INCORRECT_END_BALANCE");
    }

    @Test
    void verify_with_all_wrong_settings()
    {
        StatementProcessorResponseModel sutFirst = statementProcessorService.validate(setup(4, true));
        Assert.assertEquals(sutFirst.result, "SUCCESSFUL");
        StatementProcessorResponseModel sutSecond = statementProcessorService.validate(setup(4, false));
        Assert.assertEquals(sutSecond.result, "DUPLICATE_REFERENCE_INCORRECT_END_BALANCE");
    }
}

Edit 1: Added Service code

@Component
public class StatementProcessorService {
    private StatementProcessorResponseModel responseModel = new StatementProcessorResponseModel();
    private static ArrayList<Long> usedReferences = new ArrayList<>();

    public StatementProcessorResponseModel validate(StatementProcessorInputModel inputModel){
        if(!validateUniqueReference(inputModel.transactionReference))
        {
            responseModel.errorRecords.add("account_number_of_ inCorrectEndBalance _record");
            responseModel.result = "DUPLICATE_REFERENCE";
        }

        if(!validateMutation(inputModel))
        {
            responseModel.errorRecords.add("account_number_of_ inCorrectEndBalance _record");
            if (!responseModel.result.isBlank()){
                responseModel.result = responseModel.result + "_INCORRECT_END_BALANCE";
            }
            else{
                responseModel.result = "INCORRECT_END_BALANCE";
            }
        }

        if (responseModel.result.isBlank()){
            responseModel.result = "SUCCESSFUL";
        }
        return responseModel;
    }

Solution

  • If you mark your test cases/classes which modify the database with @Transactional then the test runner will rollback the transaction after the test.

    You can refer to the reference documentation regarding test transactions.