Adding some basic unit tests for the TenantService class. We should add more tests for other CRUD flows as well.

This commit is contained in:
Arpit Mohan 2019-09-04 09:24:38 +00:00
parent 6c90ce2561
commit bf908025e2
21 changed files with 286 additions and 48 deletions

View File

@ -18,6 +18,25 @@
<java.version>11</java.version>
</properties>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>jboss-maven2-release-repository</id>
<name>JBoss Spring Repository</name>
<url>https://repository.jboss.org/nexus/content/repositories/public/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
@ -55,6 +74,16 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.17.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
@ -71,12 +100,17 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<version>3.2.11.RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>

View File

@ -24,14 +24,14 @@ import java.util.Map;
* This code has been copied from WebSessionServerOAuth2AuthorizedClientRepository.java
* which also implements ServerOAuth2AuthorizedClientRepository. This was done to make changes
* to saveAuthorizedClient to also handle adding users to UserRepository.
*
* <p>
* This was done because on authorization, the user needs to be stored in appsmith domain.
* To achieve this, saveAuthorizedClient function has been edited in the following manner.
* In the reactive flow, post doOnSuccess transformation, another Mono.then has been added. In this,
* Authentication object is passed to checkAndCreateUser function. This object is used to get OidcUser from which
* user attributes like name, email, etc are extracted. If the user doesnt exist in User
* Repository, a new user is created and saved.
*
* <p>
* The ClientUserRepository is created during SecurityWebFilterChain Bean creation. By
* configuring to use Oauth2Login, this ServerOAuth2AuthorizedClientRepository implementation
* is injected. This hack is used to ensure that on successful authentication, we are able
@ -42,18 +42,16 @@ import java.util.Map;
@Configuration
public class ClientUserRepository implements ServerOAuth2AuthorizedClientRepository {
private static final String DEFAULT_AUTHORIZED_CLIENTS_ATTR_NAME =
WebSessionServerOAuth2AuthorizedClientRepository.class.getName() + ".AUTHORIZED_CLIENTS";
private final String sessionAttributeName = DEFAULT_AUTHORIZED_CLIENTS_ATTR_NAME;
UserService userService;
TenantService tenantService;
public ClientUserRepository(UserService userService, TenantService tenantService) {
this.userService = userService;
this.tenantService = tenantService;
}
private static final String DEFAULT_AUTHORIZED_CLIENTS_ATTR_NAME =
WebSessionServerOAuth2AuthorizedClientRepository.class.getName() + ".AUTHORIZED_CLIENTS";
private final String sessionAttributeName = DEFAULT_AUTHORIZED_CLIENTS_ATTR_NAME;
@Override
@SuppressWarnings("unchecked")
public <T extends OAuth2AuthorizedClient> Mono<T> loadAuthorizedClient(String clientRegistrationId, Authentication principal,

View File

@ -5,6 +5,9 @@ import org.springframework.context.annotation.Configuration;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;
import javax.validation.Validation;
import javax.validation.Validator;
@Configuration
public class CommonConfig {
@ -15,4 +18,8 @@ public class CommonConfig {
return Schedulers.newElastic(ELASTIC_THREAD_POOL_NAME);
}
@Bean
public Validator validator() {
return Validation.buildDefaultValidatorFactory().getValidator();
}
}

View File

@ -0,0 +1,7 @@
package com.appsmith.server.constants;
public class FieldName {
public static String TENANT = "tenant";
public static String ID = "id";
public static String NAME = "name";
}

View File

@ -47,7 +47,7 @@ public abstract class BaseController<S extends CrudService, T extends BaseDomain
}
@PutMapping("/{id}")
public Mono<ResponseDto<T>> update(@PathVariable ID id, @RequestBody T resource) throws Exception {
public Mono<ResponseDto<T>> update(@PathVariable ID id, @RequestBody T resource) {
log.debug("Going to update resource with id: {}", id);
return service.update(id, resource)
.map(updatedResource -> new ResponseDto<>(HttpStatus.OK.value(), updatedResource, null));

View File

@ -6,6 +6,7 @@ import lombok.Setter;
import lombok.ToString;
import org.springframework.data.mongodb.core.mapping.Document;
import javax.validation.constraints.NotNull;
import java.util.List;
@ -18,6 +19,7 @@ public class Tenant extends BaseDomain {
private String domain;
@NotNull
private String name;
private String website;

View File

@ -14,6 +14,7 @@ import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import javax.validation.Validator;
import javax.validation.constraints.NotNull;
@Slf4j
@ -25,25 +26,30 @@ public class ActionServiceImpl extends BaseService<ActionRepository, Action, Str
private final PluginService pluginService;
@Autowired
public ActionServiceImpl(Scheduler scheduler, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, ActionRepository repository, ResourceService resourceService, PluginService pluginService) {
super(scheduler, mongoConverter, reactiveMongoTemplate, repository);
public ActionServiceImpl(Scheduler scheduler,
Validator validator,
MongoConverter mongoConverter,
ReactiveMongoTemplate reactiveMongoTemplate,
ActionRepository repository,
ResourceService resourceService,
PluginService pluginService) {
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository);
this.repository = repository;
this.resourceService = resourceService;
this.pluginService = pluginService;
}
@Override
public Mono<Action> create(@NotNull Action action) throws AppsmithException {
public Mono<Action> create(@NotNull Action action) {
if (action.getId() != null) {
throw new AppsmithException("During create action, Id is not null. Can't create new action.");
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, "id"));
} else if (action.getResourceId() == null) {
throw new AppsmithException(AppsmithError.RESOURCE_ID_NOT_GIVEN);
return Mono.error(new AppsmithException(AppsmithError.RESOURCE_ID_NOT_GIVEN));
}
Mono<Resource> resourceMono = resourceService.findById(action.getResourceId());
Mono<Plugin> pluginMono = resourceMono.flatMap(resource -> pluginService.findById(resource.getPluginId()));
return pluginMono
//Set plugin in the action before saving.
.map(plugin -> {

View File

@ -1,5 +1,6 @@
package com.appsmith.server.services;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.BaseDomain;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
@ -15,7 +16,10 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.Map;
import java.util.Set;
public abstract class BaseService<R extends BaseRepository, T extends BaseDomain, ID> implements CrudService<T, ID> {
@ -27,20 +31,24 @@ public abstract class BaseService<R extends BaseRepository, T extends BaseDomain
protected final R repository;
protected final Validator validator;
public BaseService(Scheduler scheduler,
Validator validator,
MongoConverter mongoConverter,
ReactiveMongoTemplate reactiveMongoTemplate,
R repository) {
this.scheduler = scheduler;
this.validator = validator;
this.mongoConverter = mongoConverter;
this.mongoTemplate = reactiveMongoTemplate;
this.repository = repository;
}
@Override
public Mono<T> update(ID id, T resource) throws Exception {
public Mono<T> update(ID id, T resource) {
if (id == null) {
throw new Exception("Invalid id provided");
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.ID));
}
Query query = new Query(Criteria.where("id").is(id));
@ -52,8 +60,7 @@ public abstract class BaseService<R extends BaseRepository, T extends BaseDomain
updateMap.entrySet().stream().forEach(entry -> updateObj.set(entry.getKey(), entry.getValue()));
return mongoTemplate.updateFirst(query, updateObj, resource.getClass())
.flatMap(obj -> repository.findById(id))
.subscribeOn(scheduler);
.flatMap(obj -> repository.findById(id));
}
@Override
@ -63,13 +70,19 @@ public abstract class BaseService<R extends BaseRepository, T extends BaseDomain
@Override
public Mono<T> getById(ID id) {
if(id == null) {
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.ID));
}
return repository.findById(id)
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, "resource", id)));
}
@Override
public Mono<T> create(T object) throws AppsmithException {
return repository.save(object);
public Mono<T> create(T object) {
return Mono.just(object)
.flatMap(this::validateObject)
.flatMap(repository::save);
}
private DBObject getDbObject(Object o) {
@ -77,4 +90,22 @@ public abstract class BaseService<R extends BaseRepository, T extends BaseDomain
mongoConverter.write(o, basicDBObject);
return basicDBObject;
}
/**
* This function runs the validation checks on the object and returns a Mono.error if any of the constraints
* have been violated. If all checks pass, a Mono of the object is returned back to the caller
*
* @param obj
* @return Mono<T>
*/
protected Mono<T> validateObject(T obj) {
return Mono.just(obj)
.map(o -> validator.validate(o))
.flatMap(constraint -> {
if(constraint.isEmpty()) {
return Mono.just(obj);
}
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, constraint.stream().findFirst().get().getPropertyPath()));
});
}
}

View File

@ -1,7 +1,6 @@
package com.appsmith.server.services;
import com.appsmith.server.domains.BaseDomain;
import com.appsmith.server.exceptions.AppsmithException;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@ -9,9 +8,9 @@ public interface CrudService<T extends BaseDomain, ID> {
Flux<T> get();
Mono<T> create(T resource) throws AppsmithException;
Mono<T> create(T resource);
Mono<T> update(ID id, T resource) throws Exception;
Mono<T> update(ID id, T resource);
Mono<T> getById(ID id);
}

View File

@ -9,15 +9,18 @@ import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.stereotype.Service;
import reactor.core.scheduler.Scheduler;
import javax.validation.Validator;
@Slf4j
@Service
public class LayoutServiceImpl extends BaseService<LayoutRepository, Layout, String> implements LayoutService {
@Autowired
public LayoutServiceImpl(Scheduler scheduler,
Validator validator,
MongoConverter mongoConverter,
ReactiveMongoTemplate reactiveMongoTemplate,
LayoutRepository repository) {
super(scheduler, mongoConverter, reactiveMongoTemplate, repository);
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository);
}
}

View File

@ -21,6 +21,7 @@ import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.List;
@ -39,6 +40,7 @@ public class PluginServiceImpl extends BaseService<PluginRepository, Plugin, Str
@Autowired
public PluginServiceImpl(Scheduler scheduler,
Validator validator,
MongoConverter mongoConverter,
ReactiveMongoTemplate reactiveMongoTemplate,
PluginRepository repository,
@ -46,7 +48,7 @@ public class PluginServiceImpl extends BaseService<PluginRepository, Plugin, Str
ApplicationContext applicationContext,
ClientUserRepository clientUserRepository,
TenantService tenantService) {
super(scheduler, mongoConverter, reactiveMongoTemplate, repository);
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository);
this.userRepository = userRepository;
this.applicationContext = applicationContext;
pluginRepository = repository;
@ -66,10 +68,11 @@ public class PluginServiceImpl extends BaseService<PluginRepository, Plugin, Str
}
@Override
public Mono<Plugin> create(Plugin plugin) throws AppsmithException {
public Mono<Plugin> create(Plugin plugin) {
if (plugin.getId() != null) {
throw new AppsmithException(AppsmithError.INVALID_PARAMETER, "id");
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, "id"));
}
plugin.setDeleted(false);
return pluginRepository.save(plugin);
}

View File

@ -14,6 +14,8 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import javax.validation.Validator;
@Slf4j
@Service
public class QueryServiceImpl extends BaseService<QueryRepository, Query, String> implements QueryService {
@ -22,11 +24,12 @@ public class QueryServiceImpl extends BaseService<QueryRepository, Query, String
@Autowired
public QueryServiceImpl(Scheduler scheduler,
Validator validator,
MongoConverter mongoConverter,
ReactiveMongoTemplate reactiveMongoTemplate,
QueryRepository repository,
PluginService pluginService) {
super(scheduler, mongoConverter, reactiveMongoTemplate, repository);
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository);
this.pluginService = pluginService;
}

View File

@ -14,6 +14,7 @@ import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import javax.validation.Validator;
import javax.validation.constraints.NotNull;
@Slf4j
@ -28,19 +29,19 @@ public class ResourceServiceImpl extends BaseService<ResourceRepository, Resourc
private final PluginService pluginService;
@Autowired
public ResourceServiceImpl(Scheduler scheduler, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, ResourceRepository repository, TenantService tenantService, PluginService pluginService) {
super(scheduler, mongoConverter, reactiveMongoTemplate, repository);
public ResourceServiceImpl(Scheduler scheduler, Validator validator, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, ResourceRepository repository, TenantService tenantService, PluginService pluginService) {
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository);
this.repository = repository;
this.tenantService = tenantService;
this.pluginService = pluginService;
}
@Override
public Mono<Resource> create(@NotNull Resource resource) throws AppsmithException {
public Mono<Resource> create(@NotNull Resource resource) {
if (resource.getId() != null) {
throw new AppsmithException(AppsmithError.INVALID_PARAMETER, "id");
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, "id"));
} else if (resource.getPluginId() == null) {
throw new AppsmithException(AppsmithError.PLUGIN_ID_NOT_GIVEN);
return Mono.error(new AppsmithException(AppsmithError.PLUGIN_ID_NOT_GIVEN));
}
Mono<Tenant> tenantMono = tenantService.findByIdAndPluginsPluginId(tenantId, resource.getPluginId());

View File

@ -9,6 +9,8 @@ import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import javax.validation.Validator;
@Service
public class SettingServiceImpl extends BaseService<SettingRepository, Setting, String> implements SettingService {
@ -16,10 +18,11 @@ public class SettingServiceImpl extends BaseService<SettingRepository, Setting,
@Autowired
public SettingServiceImpl(Scheduler scheduler,
Validator validator,
MongoConverter mongoConverter,
ReactiveMongoTemplate reactiveMongoTemplate,
SettingRepository repository) {
super(scheduler, mongoConverter, reactiveMongoTemplate, repository);
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository);
this.repository = repository;
}

View File

@ -1,8 +1,11 @@
package com.appsmith.server.services;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.Setting;
import com.appsmith.server.domains.Tenant;
import com.appsmith.server.domains.TenantSetting;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.repositories.TenantRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@ -13,6 +16,7 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.List;
@ -25,11 +29,12 @@ public class TenantServiceImpl extends BaseService<TenantRepository, Tenant, Str
@Autowired
public TenantServiceImpl(Scheduler scheduler,
Validator validator,
MongoConverter mongoConverter,
ReactiveMongoTemplate reactiveMongoTemplate,
TenantRepository repository,
SettingService settingService) {
super(scheduler, mongoConverter, reactiveMongoTemplate, repository);
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository);
this.repository = repository;
this.settingService = settingService;
}
@ -47,19 +52,24 @@ public class TenantServiceImpl extends BaseService<TenantRepository, Tenant, Str
*/
@Override
public Mono<Tenant> create(Tenant tenant) {
if (tenant == null) {
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.TENANT));
}
log.debug("Going to create the tenant");
log.debug("Going to create the tenant {}", tenant.getName());
return Mono.just(tenant)
.flatMap(this::validateObject)
//transform the tenant data to embed setting object in each object in tenantSetting list.
.flatMap(this::enhanceTenantSettingList)
//Call the library function to save the updated tenant
.flatMap(tenantUpdated -> repository.save(tenantUpdated))
.subscribeOn(scheduler);
.flatMap(repository::save);
}
private Mono<Tenant> enhanceTenantSettingList(Tenant tenant) {
if (tenant.getTenantSettings() == null) tenant.setTenantSettings(new ArrayList<>());
if (tenant.getTenantSettings() == null) {
tenant.setTenantSettings(new ArrayList<>());
}
Flux<TenantSetting> tenantSettingFlux = Flux.fromIterable(tenant.getTenantSettings());
// For each tenant setting, fetch and embed the setting, and once all the tenant setting are done, collect it

View File

@ -11,16 +11,19 @@ import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import javax.validation.Validator;
@Service
public class UserServiceImpl extends BaseService<UserRepository, User, String> implements UserService, UserDetailsService {
private UserRepository repository;
public UserServiceImpl(Scheduler scheduler,
Validator validator,
MongoConverter mongoConverter,
ReactiveMongoTemplate reactiveMongoTemplate,
UserRepository repository) {
super(scheduler, mongoConverter, reactiveMongoTemplate, repository);
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository);
this.repository = repository;
}

View File

@ -10,6 +10,8 @@ import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import javax.validation.Validator;
@Service
@Slf4j
public class WidgetServiceImpl extends BaseService<WidgetRepository, Widget, String> implements WidgetService {
@ -18,10 +20,11 @@ public class WidgetServiceImpl extends BaseService<WidgetRepository, Widget, Str
@Autowired
public WidgetServiceImpl(Scheduler scheduler,
Validator validator,
MongoConverter mongoConverter,
ReactiveMongoTemplate mongoTemplate,
WidgetRepository widgetRepository) {
super(scheduler, mongoConverter, mongoTemplate, widgetRepository);
super(scheduler, validator, mongoConverter, mongoTemplate, widgetRepository);
this.widgetRepository = widgetRepository;
}

View File

@ -0,0 +1,125 @@
package com.appsmith.server.services;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.Tenant;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest
public class TenantServiceTest {
@Autowired
TenantService tenantService;
Tenant tenant;
@Before
public void setup() {
tenant = new Tenant();
tenant.setName("Test Name");
tenant.setDomain("example.com");
tenant.setWebsite("https://example.com");
}
/* Tests for the Create Tenant Flow */
@Test
public void nullCreateTenant() {
Mono<Tenant> tenantResponse = tenantService.create(null);
StepVerifier.create(tenantResponse)
.expectErrorMatches(throwable -> throwable instanceof AppsmithException &&
throwable.getMessage().equals(AppsmithError.INVALID_PARAMETER.getMessage(FieldName.TENANT)))
.verify();
}
@Test
public void nullName() {
tenant.setName(null);
Mono<Tenant> tenantResponse = tenantService.create(tenant);
StepVerifier.create(tenantResponse)
.expectErrorMatches(throwable -> throwable instanceof AppsmithException &&
throwable.getMessage().equals(AppsmithError.INVALID_PARAMETER.getMessage(FieldName.NAME)))
.verify();
}
@Test
public void validCreateTenantTest() {
Mono<Tenant> tenantResponse = tenantService.create(tenant);
StepVerifier.create(tenantResponse)
.assertNext(tenant1 -> {
assertThat(tenant1.getName()).isEqualTo("Test Name");
})
.verifyComplete();
}
/* Tests for Get Tenant Flow */
@Test
public void getTenantInvalidId() {
Mono<Tenant> tenantMono = tenantService.getById("random-id");
StepVerifier.create(tenantMono)
.expectErrorMatches(throwable -> throwable instanceof AppsmithException &&
throwable.getMessage().equals(AppsmithError.NO_RESOURCE_FOUND.getMessage("resource", "random-id")))
.verify();
}
@Test
public void getTenantNullId() {
Mono<Tenant> tenantMono = tenantService.getById(null);
StepVerifier.create(tenantMono)
.expectErrorMatches(throwable -> throwable instanceof AppsmithException &&
throwable.getMessage().equals(AppsmithError.INVALID_PARAMETER.getMessage(FieldName.ID)))
.verify();
}
@Test
public void validGetTenantByName() {
Mono<Tenant> createTenant = tenantService.create(tenant);
Mono<Tenant> getTenant = createTenant.flatMap(t -> tenantService.getById(t.getId()));
StepVerifier.create(getTenant)
.assertNext(t -> {
assertThat(t).isNotNull();
assertThat(t.getName()).isEqualTo(tenant.getName());
assertThat(t.getId()).isEqualTo(tenant.getId());
})
.verifyComplete();
}
/* Tests for Update Tenant Flow */
@Test
public void validUpdateTenant() {
Tenant tenant = new Tenant();
tenant.setName("Test Name");
tenant.setDomain("example.com");
tenant.setWebsite("https://example.com");
Mono<Tenant> createTenant = tenantService.create(tenant);
Mono<Tenant> updateTenant = createTenant
.map(t -> {
t.setDomain("abc.com");
return t;
})
.flatMap(t -> tenantService.update(t.getId(), t))
.flatMap(t -> tenantService.getById(t.getId()));
StepVerifier.create(updateTenant)
.assertNext(t -> {
assertThat(t).isNotNull();
assertThat(t.getName()).isEqualTo(tenant.getName());
assertThat(t.getId()).isEqualTo(tenant.getId());
assertThat(t.getDomain()).isEqualTo("abc.com");
})
.verifyComplete();
}
}