I'm trying to replace an @Autowired
object with a Mockito mock object. The usual way of doing this was with xml using Springockito:
<mockito:mock id="SomeMock" class="com.package.MockInterface" />
Currently I'm trying to move over to using Spring's JavaConfig to do the job. All of a sudden the Java expressions are a whole lot more verbose than xml:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class MyTestClass {
@Configuration
static class Config {
@Bean
public MockInterface somethingSpecial() {
return Mockito.mock(MockInterface.class);
}
}
@Autowired MockInterface mockObj;
// test code
}
I discovered a library called Springockito-annotations, which allows you to do the following:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader=SpringockitoContextLoader.class)
public class MyTestClass {
@Autowired @ReplaceWithMock MockInterface mockObj;
// test code
}
Clearly, a whole lot prettier :) The only problem is that this context loader doesn't allow me to use @Configuration
and JavaConfig for other beans (if I do, Spring complains that there are no candidates that match those autowired fields).
Do you guys know of a way to get Spring's JavaConfig and Springockito-annotations to play nice? Alternatively, is there another shorthand for creating mocks?
As a nice bonus, using Springockito and xml config, I was able to mock out concrete classes without providing autowiring candidates to its dependencies (if it had any). Is this not possible without xml?
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. We can specify the mock objects to be injected using @Mock or @Spy annotations.
It is because the autowired component requires an special treatment to be “mocked”. This will initialize the application context, but, if your goal is not a integration test, maybe this is unnecessary, because now, you'll have a test case with all dependencies of your project loaded (slow test!).
The Mockito. mock() method allows us to create a mock object of a class or an interface. We can then use the mock to stub return values for its methods and verify if they were called. We don't need to do anything else to this method before we can use it.
If you want to create just a Mockito test you could use the annotation @RunWith(MockitoJUnitRunner. class) instead of @SpringBootTest . But if you want to create a Spring Boot integration test then you should use @MockBean instead of @Mock and @Autowired instead of @InjectMocks .
Moving away from the now unmaintained (as of this writing) Spingockito-annotations and to Mockito, we have a way of doing this very simply:
@RunWith(MockitoJUnitRunner.class)
@ContextConfiguration
public class MyTestClass {
@Mock MockInterface mockObj;
// test code
}
If you're using a real object, but would like to mock a dependency within it, for instance testing a service layer with DAO:
@RunWith(MockitoJUnitRunner.class)
@ContextConfiguration
public class MyTestClass {
@InjectMocks RealService;
@Mock MockDAO mockDAO;
// test code
}
Finally, this can also be applied to Spring-boot, but using annotation initialization within setUp()
until multiple class runners are supported:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyMainSpringBootClass.class)
public class MyTestClass {
@InjectMocks RealService;
@Mock MockDAO mockDAO;
@Before
public final void setUp() throws Exception{
MockitoAnnotations.initMocks(this);
}
// test code
}
Please read also @ethesx answer, Springockito is unmaintaned
This is possible now to mock Spring application without any XML file with Springockito-annotations.. This solution works also with Spring Boot.
import static org.mockito.BDDMockito.*;
import org.kubek2k.springockito.annotations.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Application.class,
loader = SpringockitoAnnotatedContextLoader.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class MainControllerTest {
@Autowired
MainController mainController;
@Autowired
@ReplaceWithMock
FooService fooService;
@Test
public void shouldGetBar() {
//given
given(fooService.result("foo")).willReturn("bar");
//when
Bar bar build = fooService.getBar("foo");
//then
assertThat(bar).isNotNull();
}
}
Dependencies: org.kubek2k:springockito-annotations:1.0.9
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With