单元测试构造函数初始化和公共逻辑

bxjv4tth  于 2022-11-08  发布在  Java
关注(0)|答案(1)|浏览(134)

假设您有下列类别:

public class RepositoryImpl implements Repository {
  private static final Object DEFAULT_OBJECT = new Object();

  private final Persistence persistence;
  private volatile Object cachedObject; // maybe ignore that this is volatile and non-final

  public RepositoryImpl(Persistence persistence) {
    this.persistence = persistence;
    this.cachedObject = getInitialCachedObject();
  }

  private Object getInitialCachedObject() {
    try {
      return persistence.get();
    } catch (ObjectNotFoundException e) {
      persistence.persist(DEFAULT_OBJECT);
      return DEFAULT_OBJECT;
    }
  }

  public Object update() { /*some logic*/ }
  public Object get() { /*some logic*/ }
  public Object delete() { /*some logic*/ }
}

然后,我想对Repository类进行单元测试,并模拟持久性。我想大概有2个测试来测试初始化逻辑(快乐路径和异常),还有3个测试来测试公共方法。
问题是我应该如何进行测试?
我设法想到的可能选项有:

  • 考虑在ctor之后通过公共方法从外部调用初始化
  • 打破了不变性(在我的特殊情况下,这已经打破了,因为cachedObject需要是volatile而不是final,但在一般情况下..是的)
  • 在每个测试用例中创建RepositoryImpl,而不是使用@InjectMocks或@Before
  • 创建两个嵌套测试类-一个用于init逻辑,一个用于核心逻辑
  • 以某种方式使用@InjectMocks,但仅在一次测试中重新初始化,不确定是否可能
  • get()中的一些懒惰方法,但也打破了一般情况下的不变性

对我来说,选项3看起来很干净,但也许有一个更好的方法,或者需要进一步的重构idk。任何建议都是非常感谢的。
注意,我不能在持久性中使用@Cachable,因为这不是一个Spring项目。

i7uq4tfw

i7uq4tfw1#

1.在每个测试用例中创建RepositoryImpl,而不是使用@InjectMocks或@Before
1.创建两个嵌套测试类-一个用于init逻辑,一个用于核心逻辑
我认为上述选项是可行的解决方案,但您在这里提出了一个很好的观点:
1.以某种方式使用@InjectMocks,但仅在一次测试中重新初始化,不确定是否可能
要实现这一点,只需忽略存储在用@InjectMocks标注的测试类字段中的示例,并创建一个单独的示例,就在这个测试中(如第二个建议的方法所述)。

@ExtendWith(MockitoExtension.class)
class RepositoryTest {

    @Mock
    Persistence persistence;
    @InjectMocks
    RepositoryImpl repository;

    @Test
    void oneOfMultipleTests() {
        // here you're defining the persistence field mock behavior
        // and using the repository field
    }

    @Test
    void objectNotFound() {
        var emptyPersistence = mock(Persistence.class);
        when(emptyPersistence.get()).thenThrow(...);

        var emptyBasedRepository = new RepositoryImpl(emptyPersistence);

        assertNotNull(emptyBasedRepository);
        verify(emptyPersistence).persist(argThat(...));
        // assert something else if you want
    }

}

相关问题