标签:let tty int dom 核心 support ada 状态 access
微服务测试的最大挑战:依赖。
解决方案是采用分而治之的策略:
a.先针对每一个微服务进行隔离测试,在对每一个微服务进行测试的时候再按照分层的方式进行隔离测试;测试过程中采用mock等技术来隔离依赖简化测试;
b.在确保每个微服务通过隔离测试后,再进行整个应用的端到端集成测试
总结
分类 | 功能 |
---|---|
单元测试 | 确保类、模块功能正确 |
集成测试 | 确保组件间接口、交互、链路正确 |
组件测试 | 确保微服务作为独立整体,接口功能正确 |
契约测试 | 确保服务提供方和消费方都遵循契约规范 |
端到端测试 | 确保整个应用满足用户需求 |
探索测试 | 手工探索学习系统功能,改进自动化测试 |
# ****** H2 In Memory Database Connection Info *******
spring:
...
datasource: # use in-memory db for unit testing
url: jdbc:h2:mem:staffjoy_account;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL
username: sa
password:
driver-class-name: org.h2.Driver
continue-on-error: false
platform: h2
schema: classpath:/db/schema.sql
h2:
console:
enabled: true
jpa:
hibernate:
ddl-auto: validate
show-sql: true
properties:
hibernate:
format_sql: true
output:
ansi:
enabled: always
staffjoy:
common:
sentry-dsn: ${SENTRY_DSN:https://8822f4ae889b433f9fe72e3904665246@sentry.io/1234888} # mock for test
deploy-env: ${DEPLOY:V2}
signing-secret: ${SIGNING_SECRET:TEST_SECRET}
email-service-endpoint: http://email-service
company-service-endpoint: http://company-service
bot-service-endpoint: http://bot-service
account-service-endpoint: http://localhost:8080 # for testing only
intercom-access-token: ${INTERCOM_ACCESS_TOKEN:TEST_INTERCOM_ACCESS_TOKEN}
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.NONE)
@RunWith(SpringRunner.class)
public class AccountRepoTest {
@Autowired
private AccountRepo accountRepo;
@Autowired
private AccountSecretRepo accountSecretRepo;
private Account newAccount;
@Before
public void setUp() {
newAccount = Account.builder()
.name("testAccount")
.email("test@staffjoy.net")
.memberSince(LocalDateTime.of(2019, 1, 20, 12, 50).atZone(ZoneId.systemDefault()).toInstant())
.confirmedAndActive(false)
.photoUrl("https://staffjoy.xyz/photo/test.png")
.phoneNumber("18001801266")
.support(false)
.build();
// sanity check
accountRepo.deleteAll();
}
@Test//(expected = DuplicateKeyException.class)
public void createSampleAccount() {
accountRepo.save(newAccount);
assertTrue(accountRepo.existsById(newAccount.getId()));
}
@Test
public void getAccountById() {
accountRepo.save(newAccount);
assertEquals(1, accountRepo.count());
Account foundAccount = accountRepo.findById(newAccount.getId()).get();
assertEquals(newAccount, foundAccount);
}
...
}
case2:controller层测试,校验输入输出是否合法
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class CompanyControllerUnitTest {
@Autowired
MockMvc mockMvc;
@MockBean
CompanyService companyService;
@Autowired
ObjectMapper objectMapper;
CompanyDto newCompanyDto;
@Rule
public ExpectedException expectedEx = ExpectedException.none();
@Before
public void setUp() {
newCompanyDto = CompanyDto.builder()
.archived(false)
.name("test-company")
.defaultDayWeekStarts("Monday")
.defaultTimezone(TimeZone.getDefault().getID())
.build();
}
@Test()
public void testCreateCompanyAuthorizeMissing() throws Exception {
MvcResult mvcResult = mockMvc.perform(post("/v1/company/create")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(newCompanyDto)))
.andExpect(status().isOk())
.andReturn();
GenericCompanyResponse genericCompanyResponse = objectMapper.readValue(mvcResult.getResponse().getContentAsString(), GenericCompanyResponse.class);
assertThat(genericCompanyResponse.isSuccess()).isFalse();
assertThat(genericCompanyResponse.getCode()).isEqualTo(ResultCode.UN_AUTHORIZED);
}
@Test
public void testCreateCompanyPermissionDeniedException() throws Exception {
MvcResult mvcResult = mockMvc.perform(post("/v1/company/create")
.contentType(MediaType.APPLICATION_JSON)
.header(AuthConstant.AUTHORIZATION_HEADER, AuthConstant.AUTHORIZATION_COMPANY_SERVICE)
.content(objectMapper.writeValueAsBytes(newCompanyDto)))
.andExpect(status().isOk())
.andReturn();
GenericCompanyResponse genericCompanyResponse = objectMapper.readValue(mvcResult.getResponse().getContentAsString(), GenericCompanyResponse.class);
assertThat(genericCompanyResponse.isSuccess()).isFalse();
assertThat(genericCompanyResponse.getCode()).isEqualTo(ResultCode.UN_AUTHORIZED);
}
...
}
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@EnableFeignClients(basePackages = {"xyz.staffjoy.account.client"})
@Import(TestConfig.class)
@Slf4j
public class AccountControllerTest {
@Autowired
AccountClient accountClient;
@Autowired
EnvConfig envConfig;
@MockBean
MailClient mailClient;
@MockBean
BotClient botClient;
@Autowired
private AccountRepo accountRepo;
@Autowired
private AccountSecretRepo accountSecretRepo;
private Account newAccount;
@Before
public void setUp() {
// sanity check
accountRepo.deleteAll();
// clear CURRENT_USER_HEADER for testing
TestConfig.TEST_USER_ID = null;
}
@Test
public void testUpdateAccount() {
// arrange mock
when(mailClient.send(any(EmailRequest.class))).thenReturn(BaseResponse.builder().message("email sent").build());
when(botClient.sendSmsGreeting(any(GreetingRequest.class))).thenReturn(BaseResponse.builder().message("sms sent").build());
// first account
String name = "testAccount001";
String email = "test001@staffjoy.xyz";
String phoneNumber = "18001801236";
String subject = "Activate your Staffjoy account";
CreateAccountRequest createAccountRequest = CreateAccountRequest.builder()
.name(name)
.email(email)
.phoneNumber(phoneNumber)
.build();
// create
GenericAccountResponse genericAccountResponse = accountClient.createAccount(AuthConstant.AUTHORIZATION_WWW_SERVICE, createAccountRequest);
assertThat(genericAccountResponse.isSuccess()).isTrue();
AccountDto accountDto = genericAccountResponse.getAccount();
// update
accountDto.setName("testAccountUpdate");
accountDto.setConfirmedAndActive(true);
accountDto.setPhoneNumber("18001801237");
GenericAccountResponse genericAccountResponse1 = accountClient.updateAccount(AuthConstant.AUTHORIZATION_WWW_SERVICE, accountDto);
log.info(genericAccountResponse1.toString());
assertThat(genericAccountResponse1.isSuccess()).isTrue();
AccountDto updatedAccountDto = genericAccountResponse1.getAccount();
assertThat(updatedAccountDto).isEqualTo(accountDto);
// capture and verify
ArgumentCaptor<GreetingRequest> argument = ArgumentCaptor.forClass(GreetingRequest.class);
verify(botClient, times(1)).sendSmsGreeting(argument.capture());
GreetingRequest greetingRequest = argument.getValue();
assertThat(greetingRequest.getUserId()).isEqualTo(accountDto.getId());
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@Slf4j
public class LoginControllerTest {
@Autowired
MockMvc mockMvc;
@MockBean
AccountClient accountClient;
@Autowired
EnvConfig envConfig;
@Autowired
PageFactory pageFactory;
@Autowired
LoginController loginController;
@Test
public void testAleadyLoggedIn() throws Exception {
MvcResult mvcResult = mockMvc.perform(post("/login")
.header(AuthConstant.AUTHORIZATION_HEADER, AuthConstant.AUTHORIZATION_AUTHENTICATED_USER))
.andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:" +
HelperService.buildUrl("http", "myaccount." + envConfig.getExternalApex())))
.andReturn();
}
@Test
public void testGet() throws Exception {
MvcResult mvcResult = mockMvc.perform(get("/login"))
.andExpect(status().isOk())
.andExpect(view().name(Constant.VIEW_LOGIN))
.andExpect(content().string(containsString(pageFactory.buildLoginPage().getDescription())))
.andReturn();
log.info(mvcResult.getResponse().getContentAsString());
}
@Test
public void testLoginAndLogout() throws Exception {
String name = "test_user";
String email = "test@staffjoy.xyz";
Instant memberSince = Instant.now().minus(100, ChronoUnit.DAYS);
String userId = UUID.randomUUID().toString();
AccountDto accountDto = AccountDto.builder()
.id(userId)
.name(name)
.email(email)
.memberSince(memberSince)
.phoneNumber("18001112222")
.confirmedAndActive(true)
.photoUrl("http://www.staffjoy.xyz/photo/test_user.png")
.build();
when(accountClient.verifyPassword(anyString(), any(VerifyPasswordRequest.class)))
.thenReturn(new GenericAccountResponse(accountDto));
when(accountClient.trackEvent(any(TrackEventRequest.class)))
.thenReturn(BaseResponse.builder().message("event tracked").build());
when(accountClient.syncUser(any(SyncUserRequest.class)))
.thenReturn(BaseResponse.builder().message("user synced").build());
MvcResult mvcResult = mockMvc.perform(post("/login")
).andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:" +
HelperService.buildUrl("http", "app." + envConfig.getExternalApex())))
.andReturn();
Cookie cookie = mvcResult.getResponse().getCookie(AuthConstant.COOKIE_NAME);
assertThat(cookie).isNotNull();
assertThat(cookie.getName()).isEqualTo(AuthConstant.COOKIE_NAME);
assertThat(cookie.getPath()).isEqualTo("/");
assertThat(cookie.getDomain()).isEqualTo(envConfig.getExternalApex());
assertThat(cookie.isHttpOnly()).isTrue();
assertThat(cookie.getValue()).isNotBlank();
assertThat(cookie.getMaxAge()).isEqualTo(Sessions.SHORT_SESSION / 1000);
// remember-me
mvcResult = mockMvc.perform(post("/login")
.param("remember-me", "true"))
.andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:" +
HelperService.buildUrl("http", "app." + envConfig.getExternalApex())))
.andReturn();
cookie = mvcResult.getResponse().getCookie(AuthConstant.COOKIE_NAME);
assertThat(cookie).isNotNull();
assertThat(cookie.getName()).isEqualTo(AuthConstant.COOKIE_NAME);
assertThat(cookie.getPath()).isEqualTo("/");
assertThat(cookie.getDomain()).isEqualTo(envConfig.getExternalApex());
assertThat(cookie.isHttpOnly()).isTrue();
assertThat(cookie.getValue()).isNotBlank();
assertThat(cookie.getMaxAge()).isEqualTo(Sessions.LONG_SESSION / 1000);
// redirect-to
mvcResult = mockMvc.perform(post("/login")
.param("return_to", "ical." + envConfig.getExternalApex() + "/test"))
.andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:http://ical." + envConfig.getExternalApex() + "/test"))
.andReturn();
// redirect-to invalid
mvcResult = mockMvc.perform(post("/login")
.param("return_to", "signalx." + envConfig.getExternalApex() + "/test"))
.andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:" +
HelperService.buildUrl("http", "myaccount." + envConfig.getExternalApex())))
.andReturn();
// logout
mvcResult = mockMvc.perform(get("/logout"))
.andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:/"))
.andReturn();
cookie = mvcResult.getResponse().getCookie(AuthConstant.COOKIE_NAME);
assertThat(cookie).isNotNull();
assertThat(cookie.getName()).isEqualTo(AuthConstant.COOKIE_NAME);
assertThat(cookie.getPath()).isEqualTo("/");
assertThat(cookie.getDomain()).isEqualTo(envConfig.getExternalApex());
assertThat(cookie.getValue()).isBlank();
assertThat(cookie.getMaxAge()).isEqualTo(0);
}
}
SpringBoot + Kubernetes云原生微服务实践 - (6) 微服务测试设计和实践
标签:let tty int dom 核心 support ada 状态 access
原文地址:https://www.cnblogs.com/wnzhong/p/12146117.html