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.