Spring is a dependency injection framework and Powermock a powerful mocking framework. You might want to use both in your unit tests, when you have an hybrid approach. In this case, you might want to mock some objects and inject others.
The integration is a little tricky as Junit only allow us to specify one single runner, either PowerMock or Spring runner. So we need to instantiate a PowerMock runner and delegate to Spring for some operations.
Here's how to do.
1) Create a Spring configuration class:
package davisfiore.api; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication(scanBasePackages={"davisfiore.api"}) public class SpringConfiguration { public static void main(String[] args) { SpringApplication.run(SpringConfiguration.class, args); } }
In this class you have basic settings, like packages to scan (in this case davisfiore.api.*)
2) Add the following dependencies to your Maven pom.xml:
<!-- Spring Boot --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-docs</artifactId> <version>1.3.0.RELEASE</version> </dependency> </dependencies> <!-- Mockito --> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.9.5</version> <!--<scope>test</scope>--> </dependency> <!-- PowerMock --> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artifactId> <version>1.6.0</version> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>1.6.0</version> </dependency>
I omitted the Spring dependencies and all the other dependencies you might need into your project.
3) Create a test:
package package davisfiore.api; import davisfiore.api.SpringConfiguration; import davisfiore.api.service.ConfigCategoryBO; import davisfiore.api.dao.ConfigCategoryRepositoryImpl; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.modules.junit4.PowerMockRunnerDelegate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static org.mockito.Mockito.verify; import static org.powermock.api.mockito.PowerMockito.whenNew; // Set powemock runner @RunWith(PowerMockRunner.class) // Load Spring configuration @SpringApplicationConfiguration(classes=SpringConfiguration.class) // Delegate to Spring @PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class) @PowerMockIgnore({"javax.management.*"}) public class myTestClass { @Mock private MyDaoImpl myDao; @InjectMocks @Autowired @Qualifier("MyService") private MyService myService; @Before public void setup() throws Exception { // I don't want DI for this class... I want to mock when created whenNew(MyDaoImpl.class).withAnyArguments().thenReturn(myDao); } @Test public void runSimpleTest() { // Calls my service method to test myService.doRequest(); // Verifies that the Dao method has been called verify(myDao).query(); } }
Note that @Autowired will also autowire the child objects annotated in the same way. In order to overwrite this setting and allow us to create mocks in selected cases, we need to add the annotation @Injectmocks. So we can create any mocks using whenNew() instead of the Spring DI object.
Copyright © 2013 Welcome to the website of Davis Fiore. All Rights Reserved.