【问题标题】:How to mock a @Value class using Mockito?如何使用 Mockito 模拟 @Value 类?
【发布时间】:2021-06-17 00:01:36
【问题描述】:

我想对以下类进行单元测试:

@Data
@AllArgsConstructor
public class MyClass {

   private MyValueClass valueObject;

   public BigDecimal someMethod(int startId, int endId) {

      List<BigDecimal> values = valueObject.get(startId, endId);
      
      ...

我试图模拟MyValueClass,它看起来像:

@Value //lombok annotation
public class MyValueClass {

   private List<Data> someData;

   public List<BigDecimal> get(int startId, int endId) {

       //code to get subset of someData with ids between startId and endId

   }

但是当我运行这个 junit (jupiter) 测试时:

@ExtendWith(MockitoExtension.class)
class MyClassTest {

   private MyClass myClass;

   @Mock
   private MyValueClass valueOjectMock;

   @BeforeEach
   public void setUp() {
      myClass= new myClass(valueOjectMock);
   }

   @Test
   void test() {
      when(valueOjectMock.get(1,5))
         .thenReturn(new ArrayList<>());
      ....
   }
}

我收到以下错误:

org.mockito.exceptions.base.MockitoException: 
Cannot mock/spy class com.seasset.funds.performance.domain.FundReturns
Mockito cannot mock/spy because :
 - final class
    at org.mockito.junit.jupiter.MockitoExtension.beforeEach(MockitoExtension.java:153)

但是MyValueClass 不是最终的。为什么我会收到此错误?如何模拟这个类?

【问题讨论】:

  • 为什么要mock这个值对象?在编写单元测试时,您应该避免模拟值对象,因为这会使您的测试变得脆弱、难以维护并且不利于重构。它还违反Golden Mockito Rules之一

标签: java unit-testing junit mocking mockito


【解决方案1】:

值对象永远不应该被嘲笑。毕竟它只是一个不可变的值(这就是 lombok 使它成为最终值的原因)。如果它包含复杂的逻辑或隐藏的可变状态(因此不是真正的值对象),则不应使用@Value,而应使用您需要的各个部分(如@Getter)。

【讨论】:

  • 谢谢。 +1 什么被认为是复杂的逻辑?我只有一个get 方法,它有一些逻辑来返回someData 的子集。具体来说,它只返回来自someDataData 对象,其ID 介于startIdendId 之间。如果someData 不包括startIdendId,它会返回一个空列表。
  • 这个我不会考虑“复杂的逻辑”。我见过人们定义了一个“值对象”(即所有成员都是不可变的),它会调用外部 Web 服务。
【解决方案2】:

默认情况下,MyValueClass 上的 Lombok 注释 @Value 使您的类成为最终类:lombok value feature。如果您使用的是 Mockito 版本 1,则无法模拟最终课程:reference answer for mocking final classes。尝试使用 PowerMockito 或 Mockito v2 mockito-inline:如果您使用的是 maven:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>3.9.0</version>
    <scope>test</scope>
</dependency>

如果您想继续使用 mockito v1 进行测试,如果不影响性能,请尝试将 @Value 替换为 @Data。

【讨论】:

    猜你喜欢
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-25
    • 2016-05-08
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多