Junit 测试由于共享实例而失败(我认为)

Junit tests fail due shared instances (i think)

我认为我的问题与此问题有关: Tests pass when run individually but not when the whole test class run

我的测试都单独通过了,但是当我 运行 测试 class 时,其中两个失败了。调试显示 assertEquals 期望的状态与代码中给出的状态不同,主要是来自不同测试的状态。解决方案应该使用 @Before 或 @After 并进行清理,但我在使用它时遇到了麻烦,因为该实例是从 Spring.

自动装配的

主要问题:我的想法是否正确,我如何'reset'自动装配实例?

@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");
    }
}

编辑 1:添加了服务代码

@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;
    }

如果你标记你的测试 cases/classes 修改数据库 @Transactional 然后测试运行器将在测试后回滚事务。

可以参考reference documentation regarding test transactions.

您似乎没有使用数据库来存储状态,因此在不知道如何存储此状态的情况下很难添加完整的答案。不管 StatementProcessorService 必须以某种方式存储状态,所以我将尝试说明如何在测试之间重置此状态,也许您可​​以根据自己的情况进行调整。

从基本的 "it's stored in memory" 示例开始

class StatementProcessorService {
  // assuming you're storing state in memory for now
  // here we're just creating a shared map, which is where we presume you're putting data
  private Map<String, String> state = new HashMap<>();
}

最简单的方法是公开一种方法来从 StatementProcessorService.

外部重置状态
class StatementProcessorService {
  // ...

  /** Reset state */
  @VisibleForTesting
  public void reset() { state.clear(); }
}

您还可以使用注入状态保持器,它在测试期间本身可以公开重置方法

class StateHolder {
  // accessor/mutator methods
}

class TestStateHolder extends StateHolder {
  // ...

  public void reset() { ... }
}

class StatementProcessorService {
  @Autowired
  private StateHolder state;
}

最后,您可以使用 Mockito

模拟 StateHolder
@SpringBootTest
class StatementProcessorServiceTest {
  @MockBean StateHolder state;
}

与 Spring 一样,有很多 种方法可以实现您的目标。