Spring boot test failing to get data populated at start of test - java

I have a sql file which looks like this:
--Testdata
INSERT into cms_patch.configuration_main(document_key, config)
values('TEST/PhoenixTest', '{"b" : "c"}');
I am trying to run a test and want to seed this data to the table before that test, but the data is getting rolled back before the test happens.
Test class:
#Sql({"/sql/cms_dao_data.sql"})
public class CmsDaoImplTest extends AbstractPhoenixDao {
#Autowired
private CmsDao cmsDao;
#BeforeMethod(alwaysRun = true)
public void beforeMethod() {
this.cmsDao = new CmsDaoImpl();
}
#Test
#Sql("/sql/cms_dao_data.sql")
public void containsDocumentKey() {
Boolean result = cmsDao.containsDocumentKey("TEST/PhoenixTest");
assertTrue(result);
}
}
abstract class:
#Transactional
#TestPropertySource({"classpath:application-test.properties"})
#ContextConfiguration(classes = {RepositoryContext.class}, loader = AnnotationConfigContextLoader.class)
public abstract class AbstractPhoenixDao extends AbstractTransactionalTestNGSpringContextTests {
public AbstractPhoenixDao() {
}
}
Can someone please help me to know why the data is getting rolled back before the test happens.
the data is getting created because if I keep 2 values in insert with same primary key the sql run at start gives an error.
we are using postgres.

Related

java.lang.AssertionError: Status expected:<200> but was:<404> Spring Boot Page Not found

CheckoutController
#Controller
#Profile("!test")
public class CheckoutController {
private MonetaryAmount total = Money.of(0, EURO);
private final UniqueInventory<UniqueInventoryItem> inventory;
private final Katalog catalogue;
private List<UniqueInventoryItem> history = new ArrayList();
#Autowired
public CheckoutController(UniqueInventory<UniqueInventoryItem> _inventory, Katalog _catalogue){
inventory = _inventory;
catalogue = _catalogue;
}
//! Get Mappings
//#GetMapping("/checkout")
#RequestMapping("/checkout")
#PreAuthorize("hasRole('WORKER')")
public String checkout(Model model){
model.addAttribute("total", this.total);
model.addAttribute("history", this.history);
model.addAttribute("controller", this);
return "checkout"; // thymleafe located in proper path, visible when logged in
}
}
TestingController
#SpringBootTest
#AutoConfigureMockMvc
#ActiveProfiles("test")
public class CheckoutControllerTests {
#Autowired
MockMvc mockMvc;
#BeforeEach
public void pre() {
// code
}
#Test
public void checkout() throws Exception {
// TODO Error msg: status expected:<200> but was:<404>
mockMvc.perform(get("/checkout").with(user("paul").roles("WORKER")))
.andExpect(status().isOk());
}
}
Where it says "/checkout" above, I could put all other available routes which are accepted, but not this one and I do not know why. Again, it's visible to my once logged in running the project.
I tried using RequestMapping instead of GetMapping but that didnt work either. I googled with no success, in most cases people did not actually point to the right html file but thats not the case here either. I am lost at this point, asked my friends and colleagues with no success.
If you have any clue what it could be, improper mvc setup, yadada, please let me know!
You have conflicting profiles. Your controller is annotated with #Profile("!test") while your test is executing with #ActiveProfiles("test").

Test JPA repository for void functions and updates and deletes

I working on writing tests for a crud application. I need to test the service and repository for Delete and Update statements. How would I go about mocking the repository for delete and update since they won't be returning data?
For example:
#Override
public void makeUserActive(long userId) {
try {
Optional<UserEntity> userEntityList = usersJpaRepository.findById(userId);
UserEntity userEntity = userEntityList.get();
userEntity.setIsActive(1);
usersJpaRepository.save(userEntity);
} catch (Exception e) {
logger.error("Cant make active user", e);
}
}
How do i test the service that mocks this repository and also the repository itself since it wont be returning a value
The question is what is the thing you want to be tested?
If you would like to test your repository you can achieve this by using Springs #DataJpaTest. see Integration Testing With #DataJpaTest
If you would like to test the logic inside your makeUserActive-Method you must make sure to mock your repository.
Assuming the service which contains your makeUserActive-Method looks something like this:
public class UserService{
private final UsersJpaRepository usersJpaRepository;
public UserService(UsersJpaRepository usersJpaRepository) {
this.usersJpaRepository = usersJpaRepository;
}
public void makeUserActive(long userId){
// your code from your question
}
}
You could write your Unit Test like this:
#Test
void makeUserActiveTest(){
UsersJpaRepository repository = new InMemoryUsersJpaRepository();
UserEntity user = new UserEntity();
user = repository.save(user);
UserService service = new UserService(repository);
service.makeUserActive(user.getId());
Optional<UserEntity> activatedUser = repository.findById(user.getId());
assertTrue(activatedUser.isPresent());
assertEquals(1, activatedUser.get().isActive());
}
The InMemoryUsersJpaRepository is a self written Mock which will store all data in an internal Map. The code could look something like this:
public class InMemoryUsersJpaRepository extends UsersJpaRepository {
private Map<Long, UserEntity> users = new HashMap<>();
private Long idCounter = 1L;
#Override
public UserEntity save(UserEntity user) {
if(user.getId() == null){
user.setId(idCounter);
idCounter++;
}
users.put(user.getId(), user);
return user;
}
#Override
public Optional<UserEntity> findById(long userId) {
return Optional.of(users.get(userId));
}
}
This way you will test the logic of your makeUserActive-Method which is currently to simply set the isActivated Flag on you UserEntity.
Also I would like to warn you about the answer of Mensur Qulami.
The Code in his answer will lead to a passing test but I'am pretty sure it does not test the thing you want to be tested.
You should always test the expected and observable behaviour of your method.
In your case this would be the isActivated Flag that should be 1.
The fact that your makeUserActive-Method calls the findById and save Method of the UsersJpaRepository is a mere implementation detail and the testing of those generally lead to brittle tests.
For the methods returning void, you can simply verify that they have been called. Here's an example, that mocks both an object returning method and void returning method.
#ExtendWith(MockitoExtension.class)
class ServiceTest {
#Mock
private Repository repository;
#InjectMocks
private Service service; // assume that this is your class
#Test
void testMakeUserActive() {
// given:
final UserEntity userEntity = new UserEntity();
// mocks:
when(repository.findById(1)).thenReturn(Optional.of(userEntity));
// when:
service.makeUserActive(1);
// then:
verify(repository).findById(1);
verify(repository).save(userEntity);
}
}

How to re-create database before each test in Spring?

My Spring-Boot-Mvc-Web application has the following database configuration in application.properties file:
spring.datasource.url=jdbc:h2:tcp://localhost/~/pdk
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver
this is the only config I made. No any other configurations made by me anywhere. Nevertheless the Spring and subsystems are automatically recreate database on each web application run. Database is recreated namely on system run while it contains data after application ends.
I was not understanding this defaults and was expecting this is suitable for tests.
But when I started to run tests I found that database is recreated only once. Since tests are executed at no predefined order, this is senseless at all.
So, the question is: how to make any sense? I.e. how to make database recreate before each test as it happens at application first start?
My test class header is follows:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = myapp.class)
//#WebAppConfiguration
#WebIntegrationTest
#DirtiesContext
public class WebControllersTest {
As you see, I tried #DirtiesContext at class level and it didn't help.
UPDATE
I have a bean
#Service
public class DatabaseService implements InitializingBean {
which has a method
#Override
#Transactional()
public void afterPropertiesSet() throws Exception {
log.info("Bootstrapping data...");
User user = createRootUser();
if(populateDemo) {
populateDemos();
}
log.info("...Bootstrapping completed");
}
Now I made it's populateDemos() method to clear all data from database. Unfortunately, it does not called before each test despite #DirtiesContext. Why?
Actually, I think you want this:
#DirtiesContext(classMode = ClassMode.BEFORE_EACH_TEST_METHOD)
http://docs.spring.io/autorepo/docs/spring-framework/4.2.6.RELEASE/javadoc-api/org/springframework/test/annotation/DirtiesContext.html
#DirtiesContext may be used as a class-level and method-level
annotation within the same class. In such scenarios, the
ApplicationContext will be marked as dirty after any such annotated
method as well as after the entire class. If the
DirtiesContext.ClassMode is set to AFTER_EACH_TEST_METHOD, the context
will be marked dirty after each test method in the class.
You put it on your Test class.
Using the accepted answer in Spring-Boot 2.2.0, I was seeing JDBC syntax errors related to constraints:
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Constraint "FKEFFD698EA2E75FXEERWBO8IUT" already exists; SQL statement:
alter table foo add constraint FKeffd698ea2e75fxeerwbo8iut foreign key (bar) references bar [90045-200]
To fix this, I added #AutoConfigureTestDatabase to my unit test (part of spring-boot-test-autoconfigure):
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.boot.test.context.SpringBootTest;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest
#DirtiesContext(classMode = ClassMode.BEFORE_EACH_TEST_METHOD)
#AutoConfigureTestDatabase(replace = Replace.ANY)
public class FooRepositoryTest { ... }
To create the database you have to do what the other answers say with the spring.jpa.hibernate.ddl-auto=create-drop, now if your intent is to pupulate the database on each test then spring provides a very usefull anotation
#Transactional(value=JpaConfiguration.TRANSACTION_MANAGER_NAME)
#Sql(executionPhase=ExecutionPhase.BEFORE_TEST_METHOD,scripts="classpath:/test-sql/group2.sql")
public class GroupServiceTest extends TimeoffApplicationTests {
that is from this package org.springframework.test.context.jdbc.Sql; and you can run a before test method and a after test method. To populate the database.
Regarding creating the database each time, Say you only want your Test to have the create-drop option you can configure your tests with a custom properties with this annotation
#TestPropertySource(locations="classpath:application-test.properties")
public class TimeoffApplicationTests extends AbstractTransactionalJUnit4SpringContextTests{
Hope it helps
If you are looking for an alternative for the #DirtiesContext, this code below will help you. I used some code from this answer.
First, setup the H2 database on the application.yml file on your test resources folder:
spring:
datasource:
platform: h2
url: jdbc:h2:mem:test
driver-class-name: org.h2.Driver
username: sa
password:
After that, create a class called ResetDatabaseTestExecutionListener:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashSet;
import java.util.Set;
public class ResetDatabaseTestExecutionListener extends AbstractTestExecutionListener {
#Autowired
private DataSource dataSource;
public final int getOrder() {
return 2001;
}
private boolean alreadyCleared = false;
#Override
public void beforeTestClass(TestContext testContext) {
testContext.getApplicationContext()
.getAutowireCapableBeanFactory()
.autowireBean(this);
}
#Override
public void prepareTestInstance(TestContext testContext) throws Exception {
if (!alreadyCleared) {
cleanupDatabase();
alreadyCleared = true;
}
}
#Override
public void afterTestClass(TestContext testContext) throws Exception {
cleanupDatabase();
}
private void cleanupDatabase() throws SQLException {
Connection c = dataSource.getConnection();
Statement s = c.createStatement();
// Disable FK
s.execute("SET REFERENTIAL_INTEGRITY FALSE");
// Find all tables and truncate them
Set<String> tables = new HashSet<>();
ResultSet rs = s.executeQuery("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='PUBLIC'");
while (rs.next()) {
tables.add(rs.getString(1));
}
rs.close();
for (String table : tables) {
s.executeUpdate("TRUNCATE TABLE " + table);
}
// Idem for sequences
Set<String> sequences = new HashSet<>();
rs = s.executeQuery("SELECT SEQUENCE_NAME FROM INFORMATION_SCHEMA.SEQUENCES WHERE SEQUENCE_SCHEMA='PUBLIC'");
while (rs.next()) {
sequences.add(rs.getString(1));
}
rs.close();
for (String seq : sequences) {
s.executeUpdate("ALTER SEQUENCE " + seq + " RESTART WITH 1");
}
// Enable FK
s.execute("SET REFERENTIAL_INTEGRITY TRUE");
s.close();
c.close();
}
}
The code above will reset the database (truncate tables, reset sequences, etc) and is prepared to work with H2 database. If you are using another memory database (like HsqlDB) you need to make the necessary changes on the SQLs queries to accomplish the same thing.
After that, go to your test class and add the #TestExecutionListeners annotation, like:
#TestExecutionListeners(mergeMode =
TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS,
listeners = {ResetDatabaseTestExecutionListener.class}
)
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CreateOrderIT {
This should work.
If you not see any performance difference between this approach and #DirtiesContext, probably you are using #MockBean in your tests, what marks the Spring context as dirty and automatically reload the entire context.
With spring boot the h2 database can be defined uniquely for each test. Just override the data source URL for each test
#SpringBootTest(properties = {"spring.config.name=myapp-test-h2","myapp.trx.datasource.url=jdbc:h2:mem:trxServiceStatus"})
The tests can run in parallel.
Within the test the data can be reset by
#DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
There is library that covers "reset H2 database" feature in JUnit 5 tests:
https://github.com/cronn/test-utils#h2util
Sample usage:
#ExtendWith(SpringExtension.class)
#Import(H2Util.class)
class MyTest {
#BeforeEach
void resetDatabase(#Autowired H2Util h2Util) {
h2Util.resetDatabase();
}
// tests...
}
Maven coords:
<dependency>
<groupId>de.cronn</groupId>
<artifactId>test-utils</artifactId>
<version>0.2.0</version>
<scope>test</scope>
</dependency>
Disclaimer: I’m the author of suggested library.
If you use spring.jpa.hibernate.ddl-auto=create-drop should be enough to create/drop database?
Unless you're using some kind of Spring-Data integration (which I don't know at all), this seems like custom logic you'll need to implement yourself. Spring doesn't know about your databases, its schemas, and tables.
Assuming JUnit, write appropriate #Before and #After methods to set up and clean up your database, its tables, and data. Your tests can themselves write the data they need, and potentially clean up after themselves if appropriate.
A solution using try/resources and a configurable schema based on this answer. Our trouble was that our H2 database leaked data between test cases. So this Listener fires before each test method.
The Listener:
public class ResetDatabaseTestExecutionListener extends AbstractTestExecutionListener {
private static final List<String> IGNORED_TABLES = List.of(
"TABLE_A",
"TABLE_B"
);
private static final String SQL_DISABLE_REFERENTIAL_INTEGRITY = "SET REFERENTIAL_INTEGRITY FALSE";
private static final String SQL_ENABLE_REFERENTIAL_INTEGRITY = "SET REFERENTIAL_INTEGRITY TRUE";
private static final String SQL_FIND_TABLE_NAMES = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='%s'";
private static final String SQL_TRUNCATE_TABLE = "TRUNCATE TABLE %s.%s";
private static final String SQL_FIND_SEQUENCE_NAMES = "SELECT SEQUENCE_NAME FROM INFORMATION_SCHEMA.SEQUENCES WHERE SEQUENCE_SCHEMA='%s'";
private static final String SQL_RESTART_SEQUENCE = "ALTER SEQUENCE %s.%s RESTART WITH 1";
#Autowired
private DataSource dataSource;
#Value("${schema.property}")
private String schema;
#Override
public void beforeTestClass(TestContext testContext) {
testContext.getApplicationContext()
.getAutowireCapableBeanFactory()
.autowireBean(this);
}
#Override
public void beforeTestMethod(TestContext testContext) throws Exception {
cleanupDatabase();
}
private void cleanupDatabase() throws SQLException {
try (
Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()
) {
statement.execute(SQL_DISABLE_REFERENTIAL_INTEGRITY);
Set<String> tables = new HashSet<>();
try (ResultSet resultSet = statement.executeQuery(String.format(SQL_FIND_TABLE_NAMES, schema))) {
while (resultSet.next()) {
tables.add(resultSet.getString(1));
}
}
for (String table : tables) {
if (!IGNORED_TABLES.contains(table)) {
statement.executeUpdate(String.format(SQL_TRUNCATE_TABLE, schema, table));
}
}
Set<String> sequences = new HashSet<>();
try (ResultSet resultSet = statement.executeQuery(String.format(SQL_FIND_SEQUENCE_NAMES, schema))) {
while (resultSet.next()) {
sequences.add(resultSet.getString(1));
}
}
for (String sequence : sequences) {
statement.executeUpdate(String.format(SQL_RESTART_SEQUENCE, schema, sequence));
}
statement.execute(SQL_ENABLE_REFERENTIAL_INTEGRITY);
}
}
}
Using a custom annotation:
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#TestExecutionListeners(mergeMode =
TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS,
listeners = { ResetDatabaseTestExecutionListener.class }
)
public #interface ResetDatabase {
}
You can easily mark each test in which you want to reset the database:
#SpringBootTest(
webEnvironment = RANDOM_PORT,
classes = { Application.class }
)
#ResetDatabase
public class SomeClassIT {
You can annotate your test class with #Transactional:
import org.springframework.transaction.annotation.Transactional;
...
...
#RunWith(SpringRunner.class)
#Transactional
public class MyClassTest {
#Autowired
private SomeRepository repository;
#Before
public void init() {
// add some test data, that data would be rolled back, and recreated for each separate test
repository.save(...);
}
#Test
public void testSomething() {
// add some more data
repository.save(...);
// update some base data
repository.delete(...);
// all the changes on database done in that test would be rolled back after test finish
}
}
All tests are wrapped inside a transaction, that is rolled back at the end of each test. There are unfortunately some problems with that annotation of course, and you need to pay special attention, when for example your production code uses transactions with different score.
You could also try out https://www.testcontainers.org/ which helps you to run databases inside containers and you can create a fresh database for each test run too. It will be very slow though, since each time a container has to be created and the database server has to be started, configured and then migrations have to be run, then the test can be executed.
Nothing worked for me, but the following:
For every test class you can put the following annotations:
#TestMethodOrder(MethodOrderer.OrderAnnotation.class) //in case you need tests to be in specific order
#DataJpaTest // will disable full auto-configuration and instead apply only configuration relevant to JPA tests
#AutoConfigureTestDatabase(replace = NONE) //configures a test database to use instead of the application-defined or auto-configured DataSource
To order specific tests within the class you have to put also #Order annotation:
#Test
#Order(1) //first test
#Test
#Order(2) //second test, etc.
Rerunning the tests will not fail because of previous manipulations with db.

JUnit testing transactional methods

I am new to JUnit and trying to test a spring web service which uses JPA DAOs. I need to test a service method similar to below.
Service method is annotated with #Transactional(propagation=Propagation.REQUIRED) and ServiceObjectRepository.update() method calls a native sql query to update the db.
#Transactional(propagation=Propagation.REQUIRED)
public void serviceMethod(){
//Read DB for ServiceObject to update
//Call ServiceObjectRepository.update() method to update DB
}
ServiceObjectRepository
public interface ServiceObjectRepository extends JpaRepository<ServiceObject, Integer> {
#Query(value ="UPDATE serviceobjcet AS c SET c.objectstatus= :os WHERE c.objid = :oi", nativeQuery = true)
public Integer update(#Param("os")short objStatus,#Param("oi")int objId);
}
TestClass
#TransactionConfiguration(defaultRollback=true)
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(
locations = "classpath:service-test.xml")
#Transactional
public class ServiceHandlerTest {
#Test
public void testServiceMethod() {
//Create ServiceObject and save to DB
//Call serviceMethod()
//Read DB for updatedServiceObject
assertEquals("Test: Object should be in updated state", new Short(3), updatedServiceObject.getObjectstatus(), 0);
}
}
My test runs and rollback the db transactions. But the problem is when I read the updatedServiceObject after calling the serviceMethod it does not return the updated object. So my test fails with a NullPointerException at the assertEquals. Any idea to overcome this issue?
Finally I came up with a solution, Rather than creating ServiceObject and saving to DB in the test method, I have done it before the test method and deletion of the created objects done after the transaction. So that my test class looks like,
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "classpath:service-test.xml")
public class ServiceHandlerTest {
#Before
public void setup() {
//Create ServiceObject and save to DB
}
#Test
public void testServiceMethod() {
//Call serviceMethod()
//Read DB for updatedServiceObject
assertEquals("Test: Object should be in updated state", new Short(3), updatedServiceObject.getObjectstatus(), 0);
}
#After
public void teardown() {
//Delete created ServiceObject from DB
}
}
And I found that test method or test class does not necessary to be transactional in such a case.

Flush shared cache between integration tests

I am performing integration tests by using embedded Glassfish 3.1.2. The first thing I do in the test is to reset the database so each test have a completely fresh database to play with.
However, the problem is that the objects are persisted in the shared cache and not stored in the database. So when the next test starts it will get the old records from the cache instead of the database.
I can easily get rid of the problem by define
<property name="eclipselink.cache.shared.default" value="false"/>
in my persistence.xml file.
#BeforeClass
public static void startup() throws Exception {
container = EJBContainer.createEJBContainer();
context = container.getContext();
}
#Before
public void setUp() throws Exception {
//Clean database before every test using dbunit
}
#Test // This is the first test, works well since the test is first in order
public final void testCreateUser() throws Exception {
UserService userService = (UserService) context.lookup("java:global/galleria/galleria-ejb/UserService");
User user = new User(TEST_USER_ID, TEST_PASSWORD);
User actualUser = userService.signupUser(user);
assertTrue(actualUser != null);
assertEquals(TEST_USER_ID, actualUser.getUserId());
assertFalse(Arrays.equals(TEST_PASSWORD, actualUser.getPassword()));
logger.info("Finished executing test method {}", testMethod.getMethodName());
}
#Test // This is the second test, fails since the database not is clean
public final void testCreateUser() throws Exception {
UserService userService = (UserService) context.lookup("java:global/galleria/galleria-ejb/UserService");
User user = new User(TEST_USER_ID, TEST_PASSWORD);
User actualUser = userService.signupUser(user); // FAILS since TEST_USER_ID already in cache!!
//..
}
#Stateless
#EJB(name = "java:global/galleria/galleria-ejb/UserService", beanInterface = UserService.class)
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class UserServiceImpl implements UserService
{
#EJB
private UserRepository userRepository;
#Override
#PermitAll
public User signupUser(User user) throws UserException {
User existingUser = userRepository.findById(user.getUserId());
if (existingUser != null)
{
logger.error("Attempted to create a duplicate user.");
throw new UserException(DUPLICATE_USER);
}
try {
user = userRepository.create(user);
} catch (EntityExistsException entityExistsEx) {
logger.error("Attempted to create a duplicate user.");
throw new UserException(DUPLICATE_USER, entityExistsEx);
}
return user;
}
//..
}
However, I do not want to disable caching in persistence.xml file, since I will get performance loss later on. I only want to do it while testing. Note that I am using JTA data source here.
Any ideas?
Off topic, I am trying to learn java ee, and following the Galleria EE project and try to modify it for my needs.
Best regards
Check out http://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching
as both JPA 2.0 and EclipseLink native api allow clearing the shared cache. You could call this api at the start or end of your tests.

Categories

Resources