Testing Spring Retry Circuit Breaker - spring-boot

I am using Spring Retry Circuit Breaker in one of my Spring Boot applications as:
#CircuitBreaker(include = CustomException.class, maxAttempts = 3, openTimeout = 2000L, resetTimeout = 4000L)
StudentResponse getStudentInfo(String studentId) {
StudentResponse res = studentRepository.getInfoByStudentId(studentId);
return res;
}
#Recover
StudentResponse recoverStudentInfo(CustomException ex, String studentId) {
throw new StudentApiException("In recovery...");
}
Now I'm trying to test it using Junit 5 as:
#ExtendWith(SpringExtension.class)
#SpringBootTest
#EnableRetry
public class StudentServiceTest {
#Autowired
StudentService studentService;
#MockBean
StudentRepository studentRepository;
#Test
public void testCircuitBreakGetStudentInfo(){
String id = "id";
doThrow(CustomException.class).when(studentRepository).getInfoByStudentId(id);
StudentResponse res = this.studentService.getStudentInfo(id);
verify(studentRepository, times(3)).getInfoByStudentId(id); // this is telling that there has been 1 interaction with the mock
}
}
Then I tried:
#Test
public void testCircuitBreakGetStudentInfo(){
String id = "id";
doThrow(CustomException.class).when(studentRepository).getInfoByStudentId(id);
assertThrows(StudentApiException.class,
()->{ this.studentService.getStudentInfo(id); }); // this is also telling that there has been 1 interaction with the mock instead of 3
}
Shouldn't there be 3 interactions? Or will it be one? Any explanation will be of great help. Any other tips on testing the circuit breaker is appreciated (I could hardly find any example on testing this circuit breaker). Thanks

Related

Error when mocking a repository in unit test of a spring webflux application (using JUnit and Mockito)?

I am yet to find a solution to this.
My Test class:
#WebFluxTest(controllers = {PatronController.class})
#Import({PatronService.class}) //to satisfy PatronController dependency.
#ExtendWith({PatronParameterResolver.class})
class PatronFunctionsSpec {
private Patron patron;
private Mono<Patron> patronMono;
private final PatronService patronService = Mockito.mock(PatronService.class);
#MockBean
private PatronRepository patronRepository;
#Autowired
private WebTestClient client;
#BeforeEach
void init(Patron injectedPatron) {
patron = injectedPatron;
patronMono = Mono.just(patron);
}
//Patron Story: patron wants to create an account with us
#Nested
#DisplayName("Creating a patron.")
class CreatingPatron {
#Test
#DisplayName("PatronService.create() returns success msg in Response obj after creating patron.")
void getResponseObjFromServiceCreate() {
Flux<Patron> patronFlux = Flux.from(patronMono);
Mockito.when(patronRepository.saveAll(patronMono)).thenReturn(patronFlux);
PatronService patronService = new PatronService(patronRepository);
Mono<Response> responseStream = patronService.create(Mono.just(patron));
Mono<Response> expectedResponseStream = Mono.just(new Response("Welcome, patron. Can't show emojis yet -- sorry."));
assertEquals(expectedResponseStream, responseStream);
}
}
}
See my PatronService class with its code:
#Service
public class PatronService {
private final PatronRepository patronRepository;
public PatronService(PatronRepository patronRepository) {
this.patronRepository = patronRepository;
}
/**
*
* persists patron via PatronRepo
*/
public Mono<Response> create(Mono<Patron> patronMono) {
patronRepository.saveAll(patronMono).subscribe();
return Mono.just(new Response("Welcome, patron. Can't find the emojis yet -- sorry."));
}
}
I am testing the PatronService's create(), so need to mock and stub PatronRepository and its function respectively. But the problem is: after running the test case, I get this exception:
java.lang.NullPointerException: Cannot invoke "reactor.core.publisher.Flux.subscribe()" because "patronFlux" is null
at com.budgit.service.PatronService.create(PatronService.java:26)
How can I fix this?

Mockito with Junit for Spring

I am new to mockito, I need to write a JUnit test case for my project for both success and failure scenarios. I have 2 issues. First, in Mockito when I am using service.addSeasons() it is always giving as null. How should I get the response to make it assert? Second, what should I do to test failure with test exception as well? I am doing it like below but not sure whether it is correct or not. I am using jupiter.api.Test to run these.
Actual code :
public Mono<SuccessResponse> addSeason(String uuid, HuntsDetailSeasonsDto huntsDetailSeasonsDto) {
Flux<Hunter> hm = a.findByUuidAndIsPrimaryAndDeleted(uuid, true, false);
return hm.next().flatMap(h -> {
huntsDetailSeasonsDto.setHunterId(h.getId());
Mono<HuntsDetail> hsm = b.findByIdAndDeleted(huntsDetailSeasonsDto.getHuntId(), false);
return hsm.flatMap(hsm1 -> {
return b
.save(c.createAddSeasonsEntity(huntsDetailSeasonsDto, hsm1)).map(l -> {
SuccessResponse resp = new SuccessResponse();
return resp;
});
}).switchIfEmpty(Mono.error(new BusinessException()));
}).switchIfEmpty(Mono.error(new BusinessException()));
}
Mockito test case
#ExtendWith(SpringExtension.class)
#WebFluxTest
public class TestHuntsSeasonsService {
#InjectMocks
CLassAService service;
#MockBean
B b;
#MockBean
C c;
#MockBean
A a;
#MockBean
AppProperties properties;
#MockBean
SeasonsAdapter seasonsAdapter;
#Test
public void addSeasonTest() {
HuntsDetailSeasonsDto dto = new HuntsDetailSeasonsDto();
dto.setHunterId(1802L);
dto.setHuntId(7L);
dto.setSeasonsRef(24140L);
HuntsDetail huntsDetail = new HuntsDetail();
huntsDetail.setHunterId(1802L);
huntsDetail.setHuntCollectionId("7");
huntsDetail.setSeasonsDtl("24140");
Mockito.when(a.findByUuidAndIsPrimaryAndDeleted(CommonUtilTest.LOGGEDINUSER,
true, false)).thenReturn(CommonUtilTest.hunterFlux());
Mockito.when(b.findByIdAndDeleted(dto.getHuntId(), false))
.thenReturn(CommonUtilTest.huntsDetailMono());
Mockito.when(c.createAddSeasonsEntity(dto, CommonUtilTest.huntsDetail()))
.thenReturn(CommonUtilTest.huntsDetail());
Mockito.when(repository.save(huntsDetail)).thenReturn(Mono.just(huntsDetail));
service.addSeason(CommonUtilTest.LOGGEDINUSER, dto);
Mockito.verify(service, times(1)).addSeason(CommonUtilTest.LOGGEDINUSER, dto);
}
}

Spring Boot Testing with Mockito and ExpectedException - console printing 'null' is normal?

I'm writing some test classes for my services and noticed a weird behavior that happens after test results are returned. The console prints 'null' messages and no other information about tests. The tests work fine as I've tried to fail them to ensure that is the case. Is this the expected behavior?
#RunWith(MockitoJUnitRunner.class)
public class GradeServiceTest {
#Rule
public ExpectedException thrown = ExpectedException.none();
#Mock
private GradeRepository gradeRepository;
#Mock
private AssignmentService assignmentService;
#InjectMocks
private GradeService gradeService;
private Assignment assignment;
private Grade grade;
#Before
public void init() {
assignment = new Assignment.Builder()
.withId(0L)
.withModuleId(0L)
.withName("Test assignment")
.withWeightEnabled(false)
.withWeight(0)
.build();
grade = new Grade.Builder()
.withId(0L)
.withAssignmentId(0L)
.withGradeType(GradeType.PERCENTAGE)
.withGradeValue("50%")
.build();
}
#Test
public void shouldAddGrade() throws AssignmentException, GradeException {
// GIVEN
when(assignmentService.exists(grade.getAssignmentId())).thenReturn(true);
when(gradeRepository.insert(any())).thenReturn(grade);
// WHEN
Grade addedGrade = gradeService.addGrade(grade.getAssignmentId(), grade.getType().name(), grade.getValue());
// THEN
assertThat(addedGrade).isEqualTo(grade);
}
#Test
public void shouldNotAddGradeIfAssignmentDoesNotExist() throws AssignmentException, GradeException {
// GIVEN
when(assignmentService.exists(grade.getAssignmentId())).thenReturn(false);
// EXPECT
thrown.expect(AssignmentException.class);
thrown.expectMessage(AssignmentErrorMessages.NOT_FOUND);
// THEN
gradeService.addGrade(grade.getAssignmentId(), grade.getType().name(), grade.getValue());
}
}
I don't think this is normal behavior for each test to be printing 'null' without any other information. Could someone help me understand what is wrong with the code?
Test results:
null
null
Process finished with exit code 0

spring boot restcontroller test returns null

I'm testing the "find" method of the controler that returns a "findById" but the return is always null.
My project is structured as follows:
I have a LegalPerson entity
A repository that extends a JpaRepository
And a service that "uses" the repository.
#SpringBootTest
#AutoConfigureMockMvc
#ExtendWith(SpringExtension.class)
class LegalPersonResourceTest {
#MockBean
private LegalPersonService service;
#Autowired
private MockMvc mvc;
#Test
void find() {
var localDate = LocalDate.of(1955, 10, 25);
List<Long> subsidiaries = new ArrayList<>() {{
add(10L);
add(20L);
}};
List<Long> phones = new ArrayList<>() {{
add(50L);
add(60L);
}};
var mockLP = LegalPerson.builder()
.id(1L)
.active(true)
.companyId(1L)
.tradeName("Test Company Trade Name")
.companyName("Test Company Company Name")
.email("test#com")
.cnpj("testCNPJ")
.stateRegistration("test state Registration")
.municipalRegistration("test Municipal Resgistration")
.openingDate(localDate)
.address(1L)
.companyType(CompanyEnum.HEADOFFICE)
.subsidiaries(subsidiaries)
.phones(phones)
.build();
Mockito.doReturn(mockLP).when(service).find(1L);
}
}
I wonder what I'm forgetting, or writing wrong.
EDITED 01 :
Mockito.when(this.service.find(ArgumentMatchers.eq(1L))).thenReturn(mockLP);
mvc.perform(MockMvcRequestBuilders.get("/api/clients/lp/{id}", 1L))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().contentType("application/json;charset=UTF-8"))
.andExpect(MockMvcResultMatchers.jsonPath("$.active", Matchers.is(true)));
It works perfectly.
But if I add
.andExpect(MockMvcResultMatchers.header().string(HttpHeaders.ETAG, "\"1\""))
return null.
You only are mocking the service, but no testing anything in this code, you may want to test the controller, something like this:
import static org.mockito.BDDMockito.given;
#Test
public void shouldGetAPerson() throws Exception {
//...
given(service.find(1L)).willReturn(mockLP);
mvc.perform(MockMvcRequestBuilders.get("/person/1")
.contentType("application/json"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id", Matchers.containsString("1")));
}
Try with ArgumentMatchers
Mockito.when(this.service.find(ArgumentMatchers.eq(1L)).thenReturn(mockLP);

Any samples to unit test fallback using Hystrix Spring Cloud

I wish to test the following scenarios:
Set the hystrix.command.default.execution.isolation.thread.timeoutInMillisecond value to a low value, and see how my application behaves.
Check my fallback method is called using Unit test.
Please can someone provide me with link to samples.
A real usage can be found bellow. The key to enable Hystrix in the test class are these two annotations:
#EnableCircuitBreaker
#EnableAspectJAutoProxy
class ClipboardService {
#HystrixCommand(fallbackMethod = "getNextClipboardFallback")
public Task getNextClipboard(int numberOfTasks) {
doYourExternalSystemCallHere....
}
public Task getNextClipboardFallback(int numberOfTasks) {
return null;
}
}
#RunWith(SpringRunner.class)
#EnableCircuitBreaker
#EnableAspectJAutoProxy
#TestPropertySource("classpath:test.properties")
#ContextConfiguration(classes = {ClipboardService.class})
public class ClipboardServiceIT {
private MockRestServiceServer mockServer;
#Autowired
private ClipboardService clipboardService;
#Before
public void setUp() {
this.mockServer = MockRestServiceServer.createServer(restTemplate);
}
#Test
public void testGetNextClipboardWithBadRequest() {
mockServer.expect(ExpectedCount.once(), requestTo("https://getDocument.com?task=1")).andExpect(method(HttpMethod.GET))
.andRespond(MockRestResponseCreators.withStatus(HttpStatus.BAD_REQUEST));
Task nextClipboard = clipboardService.getNextClipboard(1);
assertNull(nextClipboard); // this should be answered by your fallBack method
}
}
Fore open the circuit in your unit test case just before you call the client. Make sure fall back is called. You can have a constant returned from fallback or add some log statements.
Reset the circuit.
#Test
public void testSendOrder_openCircuit() {
String order = null;
ServiceResponse response = null;
order = loadFile("/order.json");
// use this in case of feign hystrix
ConfigurationManager.getConfigInstance()
.setProperty("hystrix.command.default.circuitBreaker.forceOpen", "true");
// use this in case of just hystrix
System.setProperty("hystrix.command.default.circuitBreaker.forceOpen", "true");
response = client.sendOrder(order);
assertThat(response.getResultStatus()).isEqualTo("Fallback");
// DONT forget to reset
ConfigurationManager.getConfigInstance()
.setProperty("hystrix.command.default.circuitBreaker.forceOpen", "false");
// use this in case of just hystrix
System.setProperty("hystrix.command.default.circuitBreaker.forceOpen", "false");
}

Resources