java Spring Mockito @injectmocks 不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41584454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 05:58:47  来源:igfitidea点击:

Spring Mockito @injectmocks not working

javaspringunit-testingmockito

提问by Victor Tsai

Hi I'm using Mockito to test my Spring project, but the @InjectMocksseems not working in injecting a mocked service into another Spring service(bean).

嗨,我正在使用 Mockito 来测试我的 Spring 项目,但@InjectMocks似乎无法将模拟服务注入另一个 Spring 服务(bean)。

Here is my Spring service that I want to test:

这是我要测试的 Spring 服务:

@Service
public class CreateMailboxService {   
    @Autowired UserInfoService mUserInfoService; // this should be mocked
    @Autowired LogicService mLogicService;  // this should be autowired by Spring

    public void createMailbox() {
        // do mething
        System.out.println("test 2: " + mUserInfoService.getData());
    }

}

And below is the service that I want to mock:

下面是我要模拟的服务:

@Service
public class UserInfoService {
    public String getData() {
        return "original text";
    }
}

My test code is here:

我的测试代码在这里:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/root-context.xml" })
public class CreateMailboxServiceMockTest {

    @Mock
    UserInfoService mUserInfoService;

    @InjectMocks
    @Autowired
    CreateMailboxService mCreateMailboxService;

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

    @Test
    public void deleteWithPermission() {
        when(mUserInfoService.getData()).thenReturn("mocked text");

        System.out.println("test 1: " + mUserInfoService.getData());

        mCreateMailboxService.createMailbox();
    }
}

but the result would like

但结果是

test 1: mocked text
test 2: original text  // I want this be "mocked text", too

it seems that the CreateMailboxServicedidn't get the mocked UserInfoServicebut using Spring's autowired bean. Why is my @InjectMocksnot working?

似乎CreateMailboxService没有得到模拟的UserInfoService而是使用 Spring 的自动装配 bean。为什么我的@InjectMocks不工作?

Regards

问候

采纳答案by alayor

You can create packagelevel setter for mUserInfoServicein CreateMailboxServiceclass.

您可以在课堂上创建package水平设置器。mUserInfoServiceCreateMailboxService

@Service
public class CreateMailboxService {   
    @Autowired UserInfoService mUserInfoService; // this should be mocked
    @Autowired LogicService mLogicService;  // this should be autowired by Spring

    public void createMailbox() {
        // do mething
        System.out.println("test 2: " + mUserInfoService.getData());
    }

    void setUserInfoService(UserInfoService mUserInfoService) {
        this.mUserInfoService = mUserInfoService;
    }
}

Then, you can inject that mock in the test using the setter.

然后,您可以使用 setter 在测试中注入该模拟。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/root-context.xml" })
public class CreateMailboxServiceMockTest {

    @Mock
    UserInfoService mUserInfoService;

    CreateMailboxService mCreateMailboxService;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mCreateMailboxService = new CreateMailboxService();
        mCreateMailboxService.setUserInfoService(mUserInfoService);
    }

    ...
}

This way you can avoid problems with @InjectMocksand Spring annotations.

通过这种方式,您可以避免@InjectMocksSpring 注释的问题。

回答by Andreas

For those who stumbles on this thread and are running with JUnit 5 you need to replace the @RunWith(SpringJUnit4ClassRunner.class)

对于那些偶然发现此线程并使用 JUnit 5 运行的人,您需要替换 @RunWith(SpringJUnit4ClassRunner.class)

with

@ExtendWith(MockitoExtension.class) @RunWith(JUnitPlatform.class)

@ExtendWith(MockitoExtension.class) @RunWith(JUnitPlatform.class)

Further reading here https://www.baeldung.com/mockito-junit-5-extension. Unfortunately there is no hint when executing the test cases with junit 5 using the old annotation.

在此处进一步阅读https://www.baeldung.com/mockito-junit-5-extension。不幸的是,在使用旧注释使用 junit 5 执行测试用例时没有提示。

回答by Derek Nash

If you are trying to use the @Mock annotation for a test that relies directly on Spring injection, you may need to replace @Mockwith @MockBean @Inject(both annotations), and @InjectMockswith @Inject. Using your example:

如果您尝试将 @Mock 批注用于直接依赖 Spring 注入的测试,则可能需要将@Mock替换为@MockBean @Inject(两个批注),将@InjectMocks 替换@Inject。使用您的示例:

@MockBean
@Inject
UserInfoService mUserInfoService;

@Inject
CreateMailboxService mCreateMailboxService;

回答by Raj Shukla

For those who are running with JUnit 5you need to replace the @RunWith(SpringJUnit4ClassRunner.class)with @ExtendWith(MockitoExtension.class).

For further reading https://www.baeldung.com/mockito-junit-5-extension

对于那些谁与运行JUnit的5您需要更换@RunWith(SpringJUnit4ClassRunner.class)@ExtendWith(MockitoExtension.class)

进一步阅读https://www.baeldung.com/mockito-junit-5-extension

回答by Seba Cervantes

I had a pretty similar situation. I am writing it down just in case any reader is going through the same. In my case I found that the problem was that I was setting my injected variable as finalin the local class.

我有一个非常相似的情况。我把它写下来,以防万一读者遇到同样的情况。就我而言,我发现问题在于我将注入的变量设置为final在本地类中。

Following your example, I had things like this:

按照你的例子,我有这样的事情:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/root-context.xml" })
public class CreateMailboxServiceMockTest {

    @Mock
    UserInfoService mUserInfoService;

    @InjectMocks
    CreateMailboxService mCreateMailboxService = new CreateMailboxService(mUserInfoService);

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

    @Test
    public void deleteWithPermission() {
        ...
    }
}

But in this class I had it like this:

但在这门课上,我是这样的:

@Service
public class CreateMailboxService {   

    private final UserInfoService mUserInfoService; // it is NOT injecting Mocks just because it is final! (all ok with private)


    private final LogicService mLogicService;  // it is NOT injecting Mocks just because it is final! (all ok with private)

    @Autowired
    public CreateMailboxService(UserInfoService mUserInfoService, LogicService mLogicService) {
        this.mUserInfoService = mUserInfoService;
        this.mLogicService = mLogicService;
    }

    public void createMailbox() {
        ...
    }

}

Just deleting the finalcondition, @InjectMocksproblem was solved.

只要删除final条件,@InjectMocks问题就解决了。

回答by jAvA

there is no need of @Autowired annotation when you inject in the test class. And use the mock for the method to get your mocked response as the way you did for UserInfoService.That will be something like below. Mockito.when(mCreateMailboxService. getData()).thenReturn("my response");

在测试类中注入时不需要 @Autowired 注释。并使用该方法的模拟来获取模拟响应,就像您为 UserInfoService 所做的那样。这将类似于下面的内容。Mockito.when(mCreateMailboxService.getData()).thenReturn("我的回复");