Do you use Spring in a unit test?
You don’t necessarily need spring for unit tests.
@RunWith(SpringRunner.class) @SpringBootTest public class SidecarApiNotificationApplicationTests { @Autowired UserService userService; @Test public void testLoadAllUsers() { List<User> users = userService.getAllUsers(); assertNotNull(users); } }
What type of tests typically use Spring?
How can you create a shared application context in a JUnit integration test?
Spring’s integration testing support has the following primary goals:
To access the Context with the TestContext Framework in JUnit, two options to access the managed application context.
1. The first option is by implementing the ApplicationContextAware
interface or using @Autowired
on a field of the ApplicationContext
type. You can specify this in the @RunWith
annotation at the class level.
@RunWith(SpringRunner.class) @ContextConfiguration(classes = BankConfiguration.class) public class AccountServiceJUnit4ContextTests implements ApplicationContextAware { }
SpringRunner
class, which is an alias for SpringJUnit4ClassRunner
, is a custom JUnit runner helping to load the Spring ApplicationContext by using @ContextConfiguration(classes=AppConfig.class)
. In JUnit, you can simply run your test with the test runner SpringRunner
to have a test context manager integrated.@RunWith(SpringRunner.class) @ContextConfiguration(classes = BankConfiguration.class) public class AccountServiceJUnit4ContextTests { }
2. The second option to access the managed application context is by extending the TestContext support class specific to JUnit: AbstractJUnit4SpringContextTests
.
Note that if you extend this support class, you don’t need to specify SpringRunner in the @RunWith
annotation because this annotation is inherited from the parent.
@ContextConfiguration(classes = BankConfiguration.class) public class AccountServiceJUnit4ContextTests extends AbstractJUnit4SpringContextTests { }
When and where do you use @Transactional in testing?
defaultRollback
attribute of @TransactionConfiguration
.@Rollback
annotation, which requires a Boolean value, @Rollback(false)
, This is equivalent to another annotation introduced in Spring @Commit
.How are mock frameworks such as Mockito or EasyMock used?
Mockito lets you write tests by mocking the external dependencies with the desired behavior. Mock objects have the advantage over stubs in that they are created dynamically and only for the specific scenario tested.
Steps of using Mockito:
public class SimpleReviewServiceTest { private ReviewRepo reviewMockRepo = mock(ReviewRepo.class); // (1) private SimpleReviewService simpleReviewService; @Before public void setUp(){ simpleReviewService = new SimpleReviewService(); simpleReviewService.setRepo(reviewMockRepo); //(2) } @Test public void findByUserPositive() { User user = new User(); Set<Review> reviewSet = new HashSet<>(); when(reviewMockRepo.findAllForUser(user)).thenReturn(reviewSet);// (3) Set<Review> result = simpleReviewService.findAllByUser(user); // (4) assertEquals(result.size(), 1); //(5) } }
Mockito with Annotations
@Mock
: Creates mock instance of the field it annotates@InjectMocks
has a behavior similar to the Spring IoC, because its role is to instantiate testing object instances and to try to inject fields annotated with @Mock
or @Spy
into private fields of the testing object.@RunWith(MockitoJUnitRunner.class)
to initialize the mock objects.MockitoAnnotations.initMocks(this)
in the JUnit @Before
method.public class MockPetServiceTest { @InjectMocks SimplePetService simplePetService; @Mock PetRepo petRepo; @Before public void initMocks() { MockitoAnnotations.initMocks(this); } @Test p ublic void findByOwnerPositive() { Set<Pet> sample = new HashSet<>(); sample.add(new Pet()); Mockito .when(petRepo.findAllByOwner(owner)) .thenReturn(sample); Set<Pet> result = simplePetService.findAllByOwner(owner); assertEquals(result.size(), 1); } } }
Mockito in Spring Boot
@MockBean
@SpringBootTest
), this feature is automatically enabled.How is @ContextConfiguration used?
In spring-test
library, @ContextConfiguration
is a class-level annotation, that defines the location configuration file, which will be loaded for building up the application context for integration tests.
if @ContextConfiguration
is used without any attributes defined, the default behavior of spring is to search for a file named {testClassName}-context.xml
in the same location as the test class and load bean definitions from there if found.
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes={KindergartenConfig.class, HighschoolConfig.class}) @ActiveProfiles("kindergarten") public class ProfilesJavaConfigTest { @Autowired FoodProviderService foodProviderService; }
Spring Boot provides a @SpringBootTest
annotation, which can be used as an alternative to the standard spring-test @ContextConfiguration
annotation when you need Spring Boot features. The annotation works by creating the ApplicationContext used in your tests through SpringApplication.
@RunWith(SpringRunner.class) @SpringBootTest(properties = "spring.main.web-application-type=reactive") public class MyWebFluxTests { }
How does Spring Boot simplify writing tests?
spring-boot-starter-test
pulls in the following all within test scope:
testCompile('org.springframework.boot:spring-boot-starter-test')
What does @SpringBootTest do? How does it interact with @SpringBootApplication and @SpringBootConfiguration?
Spring Boot features like loading external properties and logging, are available only if you create ApplicationContext using the SpringApplication
class, which you’ll typically use in your entry point class. These additional Spring Boot features won’t be available if you use @ContextConfiguration
.
@SpringBootTest
uses SpringApplication behind the scenes to load ApplicationContext so that all the Spring Boot features will be available.
@ContextConfiguration
, it uses org. springframework.boot.test.context.SpringBootContextLoader
by default.@Configuration
classes are used.org.springframework.boot.test.web.client.TestRestTemplate
bean for use in web tests that use a fully running container.@RunWith(SpringRunner.class) @SpringBootTest( webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {"app.port=9090"}) public class CtxControllerTest { }How to define a testing class in Spring?
In order to define a test class for running in a Spring context, the following have to be done:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
in order to tell the runner class where the bean definitions come from@Autowired
to inject beans to be tested.