Spring value injection in mockito
I agree with the comment of @skaffman.
Besides your test uses the MockitoJUnitRunner
, hence it won't look for any Spring stuff, this only purpose is to initialize Mockito mocks. The ContextConfiguration
is not enough to wire things with spring. Technically with JUnit you can use the following runner if you want spring related stuff : SpringJUnit4ClassRunner
.
Also as you are writing a Unit Test you might want to reconsider the use of spring. Using spring wiring in a unit test is wrong. However if you are instead writing an Integration Test then why are you using Mockito there, it doesn't make sense (as said by skaffman) !
EDIT: Now in your code your a directly setting the CustomerServiceImpl
in your before block, that doesn't makes sense either. Spring is not involved at all there !
@Before
public void setup() {
customService = new CustomServiceImpl();
Setter.set(customService, "dataService", dataService);
}
EDIT 2: If you want to write a Unit Test of CustomerServiceImpl
, then avoid Spring stuff and inject directly the value of the property. Also you could use Mockito to inject the DataService
mock straigth into the tested instance.
@RunWith(MockitoJUnitRunner.class)
public CustomServiceImplTest{
@InjectMocks private CustomServiceImpl customServiceImpl;
@Mock private DataService dataService;
@Before void inject_url() { customServiceImpl.url = "http://..."; }
@Test public void customerService_should_delegate_to_dataService() { ... }
}
As you might have noticed I'm using a direct access to the url
field, the field can be package visible. This is a test workaround to actually inject the URL value as Mockito only injects mocks.
import org.springframework.test.util.ReflectionTestUtils;
@RunWith(MockitoJUnitRunner.class)
public CustomServiceTest{
@InjectMocks
private CustomServiceImpl customService;
@Mock
private DataService dataService;
@Before
public void setup() {
ReflectionTestUtils.setField(customService, "url", "http://someurl");
}
...
}
You should not mock the thing that you are trying to test. That is pointless since you would not be touching any of the code you are trying to test. Instead get the instance of CustomerServiceImpl
from the context.
You can autowire into a mutator (setter), rather than just annotating the private field. Then you can use that setter from your test class as well. No need to make it public, package private will do as Spring can still access it, but otherwise only your test can get in there (or other code in the same package).
@Value("#{myProp['custom.url']}")
String setUrl( final String url ) {
this.url = url;
}
I'm not a fan of autowiring differently (compared to my codebase) just for testing, but the alternative of changing the class under test, from the test, is simply unholy.