【问题标题】:How to mock method that called in other method while using Spring Dependency Injection?如何在使用 Spring 依赖注入时模拟在其他方法中调用的方法?
【发布时间】:2017-03-09 10:56:15
【问题描述】:

我有这样的事情:

public class Class1 {
    @Autowired
    Class2 class2;

    public Object class1Method {
        // Do something
        Object obj = class2.class2Method(arg);
        // Do something with obj
        return somthing;
    }
}

我正在对 Class1 进行单元测试,我想模拟 class2Method。我试图找到解决方案,我发现了这个:

Test class with a new() call in it with Mockito

我知道,如果我在 class1Method 中创建新的 Class2 实例,则此解决方案有效,但在我的情况下,我使用 Spring Dependency Injection,但我不知道该怎么做。

【问题讨论】:

  • 添加您的测试类定义..这些是集成测试吗?
  • @MaciejKowalski 不,这就是我想做模拟的原因

标签: java spring unit-testing junit mockito


【解决方案1】:

根据你是如何用 spring 构建你的 DI 的,如果你有 @Autowired 在字段上,你可以使用这样的东西

@RunWith(SpringRunner.class)
public Class1Test {

    @InjectMocks
    @Autwired
    private Class1 class1;

    @Mock
    Class2 class2;

    @BeforeMethod
    public void initMocks(){
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public Object testClass1Method {
        when(class2.class2Method(anyString()).thenReturn(expectedReturn);
        //Now test whatever you need with mocked class2.class2Method 

    }
}

如果你有构造函数 DI(@Autowired 在构造函数上),这会容易得多,并且你不需要为测试设置 spring 上下文

public Class1Test {

    private Class1 class1;

    private Class2 class2;

    @BeforeMethod
    public void initMocks(){
        class2 = mock(Class2.class);
        class1 = new Class1(class2);
    }
   //then use the same approach to mock any methods that you need
}

【讨论】:

  • 谢谢,还有其他关于它的问题:我看到有一个 @Spy 注释,你也可以用它来模拟方法。 @Spy 注解与 @Mock 用于模拟方法的注解有什么区别?
  • @Sagie @Spy 将使用真实对象,而不是 Mock 对象
【解决方案2】:

你应该去

模拟

,并让您的 JUnit 类在顶部包含此 @RunWith(MockitoJUnitRunner.class)。所以在你的情况下,你可以像这样拥有你的 Junit。

@RunWith(MockitoJUnitRunner.class)
public Class1Test {

    @InjectMocks
    private Class1 class1 = new Class1();

    @Mock
    Class2 class2;

    @Test
    public Object testClass1Method {
        // Now this will get the class2 mock instance when executed
        Object obj = class1.class1Method(arg);

    }
}

【讨论】:

  • 因此,如果我想模拟 class2Method,我将只做 when(class2.class2Method).thenReturn(theWantededResponseObject)?我看到有一个@Spy 注释,你也可以用它来模拟方法。 @Spy 注解与 @Mock 用于模拟方法的注解有什么区别?
  • mockito 中的 mock 是普通 mock,而 mockito 中的 spy 是部分 mock
【解决方案3】:

这是您可以使用Mockito 为Class1 编写单元测试的方法:

public Class1Test {

    @InjectMocks
    private Class1 class1;

    @Mock
    private Class2 class2;

    @BeforeMethod
    public void initMocks(){
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void test_method1() {

        Object obj = //instantiate it here...,

        Mockito.doReturn(obj).when(class2.class2Method(anyString());

        Assert.assertEquals(class1.class1Method(), something);
    }

}

【讨论】:

  • 谢谢,还有其他关于它的问题:我看到有一个 @Spy 注释,你也可以用它来模拟方法。 @Spy 注解与 @Mock 用于模拟方法的注解有什么区别?
  • Mock 被用来完全模拟对象,它将模拟该对象的所有方法,但是使用Spy 它将部分模拟它并保留它的一些原始方法。
  • 例如我们不需要模拟ArrayList的方法,所以我们可以在这种情况下使用@Spy而不是Mock
猜你喜欢
  • 1970-01-01
  • 2020-06-06
  • 1970-01-01
  • 2012-11-28
  • 1970-01-01
  • 1970-01-01
  • 2019-04-26
  • 1970-01-01
  • 2014-06-24
相关资源
最近更新 更多