-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathRateLimitingServiceIT.java
148 lines (116 loc) · 4.66 KB
/
RateLimitingServiceIT.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package com.behl.overseer.service;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.annotation.DirtiesContext;
import com.behl.overseer.InitializeApplicationSecretKey;
import com.behl.overseer.InitializeMysqlContainer;
import com.behl.overseer.InitializeRedisContainer;
import com.behl.overseer.entity.Plan;
import com.behl.overseer.entity.User;
import com.behl.overseer.entity.UserPlanMapping;
import com.behl.overseer.repository.PlanRepository;
import com.behl.overseer.repository.UserPlanMappingRepository;
import com.behl.overseer.repository.UserRepository;
import io.github.bucket4j.Bucket;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import net.bytebuddy.utility.RandomString;
@DirtiesContext
@SpringBootTest
@InitializeRedisContainer
@InitializeMysqlContainer
@InitializeApplicationSecretKey
class RateLimitingServiceIT {
@Autowired
private RateLimitingService rateLimitingService;
@Autowired
private UserRepository userRepository;
@Autowired
private PlanRepository planRepository;
@SpyBean
private UserPlanMappingRepository userPlanMappingRepository;
@Test
void getBucketOrCreateNewIfNotFoundInCache() {
// prepare test data in datasource
final var testData = new TestData().createTestData();
final var user = testData.getUser();
final var plan = testData.getPlan();
// invoke method under test
Bucket bucket;
bucket = rateLimitingService.getBucket(user.getId());
// assert bucket configuration are equal to user plan
assertThat(bucket.getAvailableTokens()).isEqualTo(Long.valueOf(plan.getLimitPerHour()));
// verify interaction with datasource to fetch user's active plan
// confirming the creation of bucket configuration from scratch
// on initial invocation
verify(userPlanMappingRepository).getActivePlan(user.getId());
Mockito.clearInvocations(userPlanMappingRepository);
// consume tokens from bucket
final var tokensToConsume = 5;
bucket.tryConsume(tokensToConsume);
// invoke method under test again
bucket = rateLimitingService.getBucket(user.getId());
// assert available tokens with bucket
assertThat(bucket.getAvailableTokens()).isEqualTo(plan.getLimitPerHour() - tokensToConsume);
// assert no interaction with datasource to fetch user's active plan on second
// invocation
verify(userPlanMappingRepository, times(0)).getActivePlan(user.getId());
}
@Test
void shouldClearRateLimitConfigurationInCache() {
// prepare test data in datasource
final var testData = new TestData().createTestData();
final var user = testData.getUser();
final var plan = testData.getPlan();
// create bucket for user
Bucket bucket;
bucket = rateLimitingService.getBucket(user.getId());
// assert bucket configuration are equal to user plan
assertThat(bucket.getAvailableTokens()).isEqualTo(Long.valueOf(plan.getLimitPerHour()));
// consume tokens from bucket and assert available tokens are less than plan
// configuration
final var tokensToConsume = 5;
bucket.tryConsume(tokensToConsume);
assertThat(bucket.getAvailableTokens()).isLessThan(Long.valueOf(plan.getLimitPerHour()));
// invoke method under test
rateLimitingService.reset(user.getId());
// retrieve bucket configuration for user again
bucket = rateLimitingService.getBucket(user.getId());
// assert bucket's available token are equal to original plan configuration
assertThat(bucket.getAvailableTokens()).isEqualTo(Long.valueOf(plan.getLimitPerHour()));
}
@Getter
@Setter
@RequiredArgsConstructor
class TestData {
private User user;
private Plan plan;
public TestData createTestData() {
// insert test user record in datasource
final String emailId = RandomString.make();
final String password = RandomString.make();
final User user = new User();
user.setEmailId(emailId);
user.setPassword(password);
final User savedUser = userRepository.save(user);
// fetch a plan record from datasource
final Plan plan = planRepository.findAll().get(0);
// insert an active user plan mapping record
final UserPlanMapping userPlanMapping = new UserPlanMapping();
userPlanMapping.setUserId(savedUser.getId());
userPlanMapping.setPlanId(plan.getId());
userPlanMappingRepository.save(userPlanMapping);
final var testData = new TestData();
testData.setUser(savedUser);
testData.setPlan(plan);
return testData;
}
}
}