Can I inject primitive variable into mocked class using annotation?

7.8k views Asked by At

For example I have handler:

@Component
public class MyHandler {

  @AutoWired
  private MyDependency myDependency;

  @Value("${some.count}")
  private int someCount;

  public int someMethod(){
    if (someCount > 2) {
    ...
  }
}

to test it I wrote the following test:

@RunWith(MockitoJUnitRunner.class}
class MyHandlerTest {

  @InjectMocks
  MyHandler myHandler;

  @Mock
  MyDependency myDependency;

  @Test
  public void testSomeMethod(){
    ReflectionTestUtils.setField(myHandler, "someCount", 4);
    myHandler.someMethod();
  }
}

I can mock variable someCount using ReflectionTestUtils. Can I somehow mock it using Mockito annotation?

2

There are 2 answers

0
Jeff Bowman On BEST ANSWER

There isn't a built-in way to do this, and beware that @InjectMocks has its downsides as well: Mockito's @InjectMocks is more of a courtesy than a fully-safe feature, and will fail silently if the system under test adds any fields.

Instead, consider creating a constructor or factory method for testing: Though your test code should live in your tests and not your production classes, your tests are a consumer of your class, and you can design a constructor explicitly for them.

@Component
public class MyHandler {

  @AutoWired
  private MyDependency myDependency;

  @Value("${some.count}")
  private int someCount;

  /** Visible for testing. */
  MyHandler(MyDependency myDependency, int someCount) {
    this.myDependency = myDependency;
    this.someCount = someCount;
  }

  // ....
}
0
luboskrnac On

Just use constructor injection:

@Component
public class MyHandler {
  private MyDependency myDependency;
  private int someCount;

  @Autowired
  public MyHandler(MyDependency myDependency,  
    @Value("${some.count}") int someCount){
      this.myDependency = myDependency;
      this.someCount = someCount;
  }

  public int someMethod(){
    if (someCount > 2) {
    ...
  }
}

and you don't need to use InjectMocks nor reflection in test. You will just create testing object via constructor and pass in the someCount value. Annotations will be ignored during test.