6

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?

luboskrnac
  • 23,973
  • 10
  • 81
  • 92
Vova Yatsyk
  • 3,245
  • 3
  • 20
  • 34
  • This answer gives the alternative that we use: create a `Properties` bean for your test, and have Spring wire those values into the `@Value` annotations: http://stackoverflow.com/a/23224535/1777072 – David Lavender Jun 10 '15 at 15:24

2 Answers2

8

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.

luboskrnac
  • 23,973
  • 10
  • 81
  • 92
0

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;
  }

  // ....
}
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251