使用@InjectMocks将@Autowired字段替换为模拟的实现

时间:2016-07-21 23:50:58

标签: java unit-testing junit spring-boot mockito

我想在我的spring boot应用程序中使用我专门为测试创建的该类的模拟实现来替换服务的自动连接类。

我选择创建这个模拟的实现,因为这个类的行为太复杂了,无法使用mockito进行模拟,因为它需要多个其他模拟本身。

我无法弄清楚如何将这个模拟的实现注入服务。

以下是这种情况的最小例子:

@Service
public class ServiceIWantToTestImpl implements ServiceIWantToTest{

    @Autowired
    ComplicatedDependency complicatedDependency;

    @Override
    public void methodUsingDependency(){
        String string = complicatedDependency.doSomething();
        System.out.println(string);
    }

}


public class MockComplicatedDependency implements ComplicatedDepencency{

    public MockComplicatedDependency(...){
        // Inject other mocked objects into this mock
    }

    public String doSomthing(){
        // This would be a mocked version of this function for testing
        return "test";
    }

}

@RunWith(MockitoJUnitRunner.class)
public class TestingTheService(){
    @InjectMock
    private static ServiceIWantToTest serviceIWantToTest = new ServiceIWantToTestImpl();

    @Mock
    ComplicatedDependency mockComplicatedDependency;

    @BeforeClass
    public static void init(){
        mockComplicatedDependency = new MockComplicatedDependency(...);
    }

    @Test
    public void testAttempt(){
        serviceIWantToTest.methodUsingDependency();  // This method calls complicatedDependency.doSomething() which does not run the mocked version in MockComplicatedDependency which I wanted to inject, and would always return null instead of the "test" string I put in this example.
    }

}

1 个答案:

答案 0 :(得分:4)

您是否必须使用Mockito注释来为被测试的类设置依赖项?

如果那不是主要约束为什么不进行简单的简单设置,并在ServiceIWantToTestImpl类的ComplicatedDependency类中引入构造函数或setter并设置您在测试设置中直接依赖于您喜欢的任何复杂依赖项,例如:

@Service
public class ServiceIWantToTestImpl implements ServiceIWantToTest {

    @Autowired
    ComplicatedDependency complicatedDependency;

    public ServiceIWantToTestImpl() {

    }

    public ServiceIWantToTestImpl(ComplicatedDependency complicatedDependency) {
        this.complicatedDependency = complicatedDependency;
    }

    @Override
    public void methodUsingDependency(){
        String string = complicatedDependency.doSomething();
        System.out.println(string);
    }
}

public class TestingTheService {

    private static ServiceIWantToTestImpl serviceIWantToTest;

    @BeforeClass
    public static void init(){
        serviceIWantToTest = new ServiceIWantToTestImpl(new MockComplicatedDependency());
    }

    @Test
    public void testAttempt() {
        serviceIWantToTest.methodUsingDependency();
    }

}

这是一种方式。

为了让它与Mockito一起使用,你可以使用@ Spy代替@Mock,如下所示:

@RunWith(MockitoJUnitRunner.class)
public class TestingTheService {

    @InjectMocks
    private static ServiceIWantToTestImpl serviceIWantToTest = new ServiceIWantToTestImpl();

    @Spy
    private static ComplicatedDependency complicatedDependency = new MockComplicatedDependency();

    @BeforeClass
    public static void init() {

    }

    @Test
    public void testAttempt() {
        serviceIWantToTest.methodUsingDependency();
    }

}

虽然这有点像黑客。我强烈建议你阅读@Spy注释的JavaDoc,并确保它的预期用途是你真正需要的测试。