Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 851 Vote(s) - 3.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Mockito: Inject real objects into private @Autowired fields

#1
I'm using Mockito's `@Mock` and `@InjectMocks` annotations to inject dependencies into private fields which are annotated with Spring's `@Autowired`:

@RunWith(MockitoJUnitRunner.class)
public class DemoTest {
@Mock
private SomeService service;

@InjectMocks
private Demo demo;

/* ... */
}

and

public class Demo {

@Autowired
private SomeService service;

/* ... */
}

Now I would like to also inject **real** objects into private `@Autowired` fields (without setters). Is this possible or is the mechanism limited to injecting Mocks only?
Reply

#2
In Addition to @Dev Blanked answer, if you want to use an existing bean that was created by Spring the code can be modified to:


@RunWith(MockitoJUnitRunner.class)
public class DemoTest {

@Inject
private ApplicationContext ctx;

@Spy
private SomeService service;

@InjectMocks
private Demo demo;

@Before
public void setUp(){
service = ctx.getBean(SomeService.class);
}

/* ... */
}

This way you don't need to change your code (add another constructor) just to make the tests work.
Reply

#3
Use `@Spy` annotation


@RunWith(MockitoJUnitRunner.class)
public class DemoTest {
@Spy
private SomeService service = new RealServiceImpl();

@InjectMocks
private Demo demo;

/* ... */
}

Mockito will consider all fields having `@Mock` or `@Spy` annotation as potential candidates to be injected into the instance annotated with `@InjectMocks` annotation. In the above case `'RealServiceImpl'` instance will get injected into the 'demo'

For more details refer

[Mockito-home][1]

[@Spy][2]

[@Mock][3]


[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

Reply

#4
Mockito is not a DI framework and even DI frameworks encourage constructor injections over field injections.
So you just declare a constructor to set dependencies of the class under test :


@Mock
private SomeService serviceMock;

private Demo demo;

/* ... */
@BeforeEach
public void beforeEach(){
demo = new Demo(serviceMock);
}

Using Mockito `spy` for the general case is a terrible advise. It makes the test class brittle, not straight and error prone : What is really mocked ? What is really tested ?
`@InjectMocks` and `@Spy` also hurts the overall design since it encourages bloated classes and mixed responsibilities in the classes.
Please [read the `spy()` javadoc][1] before using that blindly (emphasis is not mine) :

> Creates a spy of the real object. The spy calls **real** methods unless
> they are stubbed. Real spies should be used **carefully and
> occasionally**, for example when dealing with legacy code.
>
> As usual you are going to read the `partial mock warning`: Object
> oriented programming tackles complexity by dividing the complexity
> into separate, specific, SRPy objects. How does partial mock fit into
> this paradigm? Well, it just doesn't... Partial mock usually means
> that the complexity has been moved to a different method on the same
> object. In most cases, this is not the way you want to design your
> application.
>
> However, there are rare cases when partial mocks come handy: dealing
> with code you cannot change easily (3rd party interfaces, interim
> refactoring of legacy code etc.) However, I wouldn't use partial mocks
> for new, test-driven & well-designed code.



[1]:

[To see links please register here]

-
Reply

#5
I know this is an old question, but we were faced with the same problem when trying to inject Strings. So we invented a JUnit5/Mockito extension that does exactly what you want:

[To see links please register here]


EDIT:

```
@InjectionMap
private Map<String, Object> injectionMap = new HashMap<>();

@BeforeEach
public void beforeEach() throws Exception {
injectionMap.put("securityEnabled", Boolean.TRUE);
}

@AfterEach
public void afterEach() throws Exception {
injectionMap.clear();
}
```
Reply

#6
In Spring there is a dedicated utility called `ReflectionTestUtils` for this purpose. Take the specific instance and inject into the the field.

```java

@Spy
..
@Mock
..

@InjectMock
Foo foo;

@BeforeEach
void _before(){
ReflectionTestUtils.setField(foo,"bar", new BarImpl());// `bar` is private field
}
```
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through