Injecting a String property with @InjectMocks

injectmocks with constructor arguments
injectmocks not working
you haven't provided the instance at field declaration so i tried to construct the instance.
injectmocks mock private method
mockito injectmocks without annotation
junit inject dependency
injectmocks abstract class
powermockito injectmocks

I have a Spring MVC @Controller with this constructor:

@Autowired
public AbcController(XyzService xyzService, @Value("${my.property}") String myProperty) {/*...*/}

I want to write a standalone unit test for this Controller:

@RunWith(MockitoJUnitRunner.class)
public class AbcControllerTest {

    @Mock
    private XyzService mockXyzService;

    private String myProperty = "my property value";

    @InjectMocks
    private AbcController controllerUnderTest;

    /* tests */
}

Is there any way to get @InjectMocks to inject my String property? I know I can't mock a String since it's immutable, but can I just inject a normal String here?

@InjectMocks injects a null by default in this case. @Mock understandably throws an exception if I put it on myProperty. Is there another annotation I've missed that just means "inject this exact object rather than a Mock of it"?

You cannot do this with Mockito, because, as you mentioned yourself, a String is final and cannot be mocked.

There is a @Spy annotation which works on real objects, but it has the same limitations as @Mock, thus you cannot spy on a String.

There is no annotation to tell Mockito to just inject that value without doing any mocking or spying. It would be a good feature, though. Perhaps suggest it at the Mockito Github repository.

You will have to manually instantiate your controller if you don't want to change your code.

The only way to have a pure annotation based test is to refactor the controller. It can use a custom object that just contains that one property, or perhaps a configuration class with multiple properties.

@Component
public class MyProperty {

    @Value("${my.property}")
    private String myProperty;

    ...
}

This can be injected into the controller.

@Autowired
public AbcController(XyzService xyzService, MyProperty myProperty) { 
    ... 
}

You can mock and inject this then.

@RunWith(MockitoJUnitRunner.class)
public class AbcControllerTest {

    @Mock
    private XyzService mockXyzService;

    @Mock
    private MyProperty myProperty;

    @InjectMocks
    private AbcController controllerUnderTest;

    @Before
    public void setUp(){
        when(myProperty.get()).thenReturn("my property value");
    }

    /* tests */
}

This is not pretty straight forward, but at least you will be able to have a pure annotation based test with a little bit of stubbing.

Mockito @InjectMocks - Mocks Dependency Injection, Mockito @InjectMocks annotations allow us to inject mocked dependencies in the annotated class public interface Service { public boolean send(String msg); } //For Property Setter Based @InjectMocks injection public class AppServices1​  Mockito @InjectMocks annotations allow us to inject mocked dependencies in the annotated class mocked object. This is useful when we have external dependencies in the class we want to mock.

You can't do this with Mockito, but Apache Commons actually has a way to do this using one of its built in utilities. You can put this in a function in JUnit that is run after Mockito injects the rest of the mocks but before your test cases run, like this:

@InjectMocks
MyClass myClass;

@Before
public void before() throws Exception {
    FieldUtils.writeField(myClass, "fieldName", fieldValue, true);
}

Mockito: Why You Should Not Use InjectMocks Annotation to , Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection in order and as described below. If any of  To do this, we use @InjectMocks annotation. @InjectMocks marks a field on which injection should be performed. Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection – in this order. If any of the given injection strategy fail, then Mockito won’t report failure.

Since you're using Spring, you can use the org.springframework.test.util.ReflectionTestUtils from the spring-test module. It neatly wraps setting a field on a object or a static field on a class (along with other utility methods).

@RunWith(MockitoJUnitRunner.class)
public class AbcControllerTest {

    @Mock
    private XyzService mockXyzService;

    @InjectMocks
    private AbcController controllerUnderTest;

    @Before
    public void setUp(){
        ReflectionTestUtils.setField(controllerUnderTest, "myProperty", 
               "String you want to inject");
    }

    /* tests */
}

Annotation Magic with Mockito: InjectMocks • Nearsoft, Minimize repetitive mock and spy injection. Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection, in order. If any of  @InjectMocks – creates objects and inject mocked dependencies Use @InjectMocks to create class instances which needs to be tested in test class. Use @InjectMocks when actual method body needs to be executed for a given class. Use @InjectMocks when we need all internal dependencies initialized with mock objects to work method correctly.

Just don't use @InjectMocks in that case.

do:

@Before
public void setup() {
 controllerUnderTest = new AbcController(mockXyzService, "my property value");
}

Mockito and constructor + field injection, It turns out that when using @InjectMocks annotation, Mockito injects mocks only to the thenReturn(somePreparedMessage); final String  Now – let's discuss how to use @InjectMocks annotation – to inject mock fields into the tested object automatically. In the following example – we use @InjectMocks to inject the mock wordMap into the MyDictionary dic:

What you can use is this : org.mockito.internal.util.reflection.Whitebox

  1. Refactor your "AbcController" class constructor
  2. In your Test class "before" method, use Whitebox.setInternalState method to specify whatever string you want

    @Before
    public void setUp(){
        Whitebox.setInternalState(controllerUnderTest, "myProperty", "The string that you want"); }
    

mockito, In such cases you can use reflection to set such properties. This is a snippet from such JUnit test. @InjectMocks private GreetingsService greetingsService = new setField(greetingsService, // inject into this object "name", // assign to this field setField(Object targetObject, String name, Object value) method here to simplify  Because the 'Constructor injection' works successfully, so the Property setter injection will not be processed. Finally, we get a WebConfig instance with its OpConfig field remains null. After analyzing the reason, I think when test any class which explicitly or implicitly has a super class(not Object), this problem will happen.

Creating Mocks and Spies in Mockito with Code Examples, InjectMocks annotation actually tries to inject mocked dependencies using a Constructor is not there, Mockito tries to inject using property setters. to provide any Integer and String value respectively without any specific  This is the way to express null as a property value. *Note: only apply to full property values, not to parts of them. – ConversionService Bean is used to inject more complex property types as List/Array, DateTime… We can use addConverter to register a Converter. Our example will convert a string to a regular expression object Pattern.

InjectMocks, Minimizes repetitive mock and spy injection. Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection in order and as  In this article we'll show how to use dependency injection to insert Mockito mocks into Spring Beans for unit testing. In real-world applications, where components often depend on accessing external systems, it's important to provide proper test isolation so that we can focus on testing the functionality of a given unit without having to

Mockito annotations, The @Mock annotation is used to create and inject mocked instances. We do HashMap<String, Integer> mockHashMap; Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection – in this order. The @InjectMocks annotation makes it easier and cleaner to inject mocks into your code. @InjectMocks It allows you to mark a field on which an injection is to be performed.

Comments
  • I know I can just manually instantiate my controller in a setup method, but I'm hoping to find a solution the annotation configuration style. Thanks!
  • That's unfortunate. I looked through their issue tool, and it looks like they've discussed it before. General idea seems to be that it's out-of-scope for a mocking framework, and possibly even a code smell, though I don't think I agree with that. Thanks for your help!