java etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
java etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

Lombok Kullanım Rehberi: Tüm Anotasyonlar ve Pratik Örneklerle Detaylı Anlatım

Lombok, Java dilinde yazılım geliştirmeyi kolaylaştıran bir kütüphanedir. Kendi başına birçok tekrarlanan kodu yazmayı ortadan kaldırarak geliştiricilerin daha verimli çalışmalarını sağlar. Lombok'un sunduğu özellikleri, kurulumu ve kullanımı hakkında detaylı bir rehber hazırlayalım.



Lombok Nedir?

Lombok, Java projelerinde kod tekrarlamalarını azaltmak için kullanılan bir kütüphanedir. Getirici ve ayarlayıcı (getter and setter) metodlarını, equals(), hashCode(), toString() metodlarını, yapılandırıcı (constructor) metodlarını otomatik olarak oluşturabilir ve daha fazlasını yapabilir. Bu sayede kodunuzu daha temiz ve yönetilebilir hale getirir.

Lombok Nasıl Kurulur?

Maven Kullanarak Kurulum

  1. pom.xml dosyanıza aşağıdaki bağımlılığı ekleyin:
    xml
    <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.22</version> <scope>provided</scope> </dependency>

Gradle Kullanarak Kurulum

  1. build.gradle dosyanıza aşağıdaki bağımlılığı ekleyin:
    groovy
    dependencies { compileOnly 'org.projectlombok:lombok:1.18.22' annotationProcessor 'org.projectlombok:lombok:1.18.22' }

IDE Entegrasyonu

Lombok kullanmak için IDE'nizin de Lombok desteklemesi gerekmektedir.

  • IntelliJ IDEA: Lombok eklentisini yükleyin (Settings > Plugins > Marketplace).
  • Eclipse: Lombok jar dosyasını indirip javaagent olarak ekleyin (Eclipse Kurulum Dizini > eclipse.ini).

Lombok Anotasyonları

@Getter ve @Setter

Bu anotasyonlar sınıf seviyesinde veya alan seviyesinde kullanılarak getter ve setter metodlarını otomatik olarak oluşturur.

java
import lombok.Getter; import lombok.Setter; @Getter @Setter public class User { private String name; private int age; }

@ToString

Bu anotasyon, toString() metodunu otomatik olarak oluşturur.

java
import lombok.ToString; @ToString public class User { private String name; private int age; }

@EqualsAndHashCode

Bu anotasyon, equals() ve hashCode() metodlarını otomatik olarak oluşturur.

java
import lombok.EqualsAndHashCode; @EqualsAndHashCode public class User { private String name; private int age; }

@NoArgsConstructor, @AllArgsConstructor ve @RequiredArgsConstructor

Bu anotasyonlar, farklı türlerde yapılandırıcılar oluşturur.

java
import lombok.NoArgsConstructor; import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; @NoArgsConstructor @AllArgsConstructor @RequiredArgsConstructor public class User { private String name; private final int age; }

@Data

Bu anotasyon, @Getter, @Setter, @ToString, @EqualsAndHashCode ve @RequiredArgsConstructor anotasyonlarını bir araya getirir.

java
import lombok.Data; @Data public class User { private String name; private int age; }

@Builder

Bu anotasyon, Builder tasarım desenini uygulamak için kullanılır.

java
import lombok.Builder; @Builder public class User { private String name; private int age; }

@Value

Bu anotasyon, immutable (değişmez) sınıflar oluşturmak için kullanılır.

java
import lombok.Value; @Value public class User { private String name; private int age; }

@Singular

Bu anotasyon, koleksiyonları tekil öğeler olarak eklemek için @Builder anotasyonu ile birlikte kullanılır.

java
import lombok.Builder; import lombok.Singular; import java.util.List; @Builder public class User { private String name; private int age; @Singular private List<String> tags; }

Diğer Faydalı Anotasyonlar

  • @Cleanup: Kaynakları otomatik olarak temizler.
  • @Synchronized: Thread-safe metodlar oluşturur.
  • @Slf4j, @Log, vb.: Farklı logging framework'leri için loglama desteği sağlar.

Sonuç

Lombok, Java projelerinde kod tekrarlamalarını azaltarak geliştirme sürecini hızlandıran ve kodun okunabilirliğini artıran güçlü bir kütüphanedir. Doğru kullanıldığında, yazılım geliştiricilere büyük avantajlar sağlar.

Bu rehber, Lombok'un temel özelliklerini ve kullanımını kapsamaktadır. Daha fazla bilgi ve detaylı dokümantasyon için Lombok'un resmi web sitesini ziyaret edebilirsiniz: Project Lombok.

Getter ve @Setter

Getter ve Setter metotları ile bir sınıfın alanlarına erişimi yönetmek yaygındır. Örneğin, kullanıcı bilgilerinin tutulduğu bir sınıfta:

java
import lombok.Getter; import lombok.Setter; @Getter @Setter public class User { private String name; private int age; } // Kullanımı User user = new User(); user.setName("Eda"); user.setAge(30); System.out.println(user.getName()); // Eda System.out.println(user.getAge()); // 30

@ToString

Bu anotasyon ile bir nesnenin okunabilir şekilde yazdırılması sağlanır. Örneğin:

java
import lombok.ToString; @ToString public class User { private String name; private int age; } // Kullanımı User user = new User(); user.setName("Eda"); user.setAge(30); System.out.println(user.toString()); // User(name=Eda, age=30)

@EqualsAndHashCode

Bu anotasyon ile equals() ve hashCode() metodları otomatik oluşturulur. Örneğin:

java
import lombok.EqualsAndHashCode; @EqualsAndHashCode public class User { private String name; private int age; } // Kullanımı User user1 = new User(); user1.setName("Eda"); user1.setAge(30); User user2 = new User(); user2.setName("Eda"); user2.setAge(30); System.out.println(user1.equals(user2)); // true

@NoArgsConstructor, @AllArgsConstructor ve @RequiredArgsConstructor

Bu anotasyonlar farklı türlerde yapılandırıcılar oluşturur.

java
import lombok.NoArgsConstructor; import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; @NoArgsConstructor @AllArgsConstructor @RequiredArgsConstructor public class User { private String name; private final int age; } // Kullanımı User user1 = new User(); // NoArgsConstructor User user2 = new User("Eda", 30); // AllArgsConstructor User user3 = new User(30); // RequiredArgsConstructor

@Data

Bu anotasyon, getter, setter, toString, equals, hashCode ve required args constructor'ı bir araya getirir.

java
import lombok.Data; @Data public class User { private String name; private int age; } // Kullanımı User user = new User(); user.setName("Eda"); user.setAge(30); System.out.println(user.toString()); // User(name=Eda, age=30)

@Builder

Bu anotasyon, Builder tasarım desenini uygular.

java
import lombok.Builder; @Builder public class User { private String name; private int age; } // Kullanımı User user = User.builder() .name("Eda") .age(30) .build(); System.out.println(user); // User(name=Eda, age=30)

@Value

Bu anotasyon, immutable sınıflar oluşturmak için kullanılır.

java
import lombok.Value; @Value public class User { private String name; private int age; } // Kullanımı User user = new User("Eda", 30); System.out.println(user.getName()); // Eda

@Singular

Bu anotasyon, koleksiyonları tekil öğeler olarak eklemek için @Builder ile birlikte kullanılır.

java
import lombok.Builder; import lombok.Singular; import java.util.List; @Builder public class User { private String name; private int age; @Singular private List<String> tags; } // Kullanımı User user = User.builder() .name("Eda") .age(30) .tag("developer") .tag("teacher") .build(); System.out.println(user.getTags()); // [developer, teacher]

@Cleanup

Bu anotasyon, kaynakları otomatik olarak temizler.

java
import lombok.Cleanup; import java.io.FileInputStream; import java.io.IOException; public class Example { public void readFile(String path) throws IOException { @Cleanup FileInputStream fileInputStream = new FileInputStream(path); // fileInputStream kullanılabilir } }

@Synchronized

Bu anotasyon, thread-safe metotlar oluşturur.

java
import lombok.Synchronized; public class Example { private final Object lock = new Object(); @Synchronized public void safeMethod() { // thread-safe kod } @Synchronized("lock") public void safeMethodWithLock() { // thread-safe kod with custom lock } }

@Slf4j, @Log, vb.

Bu anotasyonlar, farklı logging framework'leri için loglama desteği sağlar.

java
import lombok.extern.slf4j.Slf4j; @Slf4j public class Example { public void logExample() { log.info("Logging with Lombok @Slf4j"); } } // Kullanımı Example example = new Example(); example.logExample(); // [INFO] Logging with Lombok @Slf4j

Her bir anotasyonun kullanım senaryosu, projede hangi ihtiyaçların olduğuna bağlı olarak değişebilir. Lombok, doğru kullanıldığında Java projelerinde kod tekrarlamasını azaltarak geliştirme sürecini hızlandırır.

Spring Boot ile Kullanıcı Mikro Servisi Oluşturma: Java 21, Spring Security ve JWT Kullanarak Adım Adım Rehber



User Microservice - Baştan Kodlama

Aşağıda, tüm ayrıntılarıyla User microservice'i yeniden baştan kodlayacağız.

1. Proje Yapılandırması

1.1. pom.xml

xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId> <artifactId>user-service</artifactId> <version>1.0.0</version> <properties> <java.version>21</java.version> <spring.boot.version>3.1.0</spring.boot.version> <mapstruct.version>1.5.2.Final</mapstruct.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-resource-server</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-jose</artifactId> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>21</source> <target>21</target> <annotationProcessorPaths> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>${mapstruct.version}</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build> </project>

2. application.yml

server: port: 8081 spring: datasource: url: jdbc:postgresql://localhost:5432/usersdb username: postgres password: password driver-class-name: org.postgresql.Driver jpa: hibernate: ddl-auto: update show-sql: true security: oauth2: resourceserver: jwt: issuer-uri: http://localhost:8080/oauth2/default jwt: secret: myJwtSecret expiration: 86400000 # 1 day in milliseconds

3. Model, Repository, Service ve Controller Katmanları

3.1. User Entity

package com.example.userservice.model; import jakarta.persistence.*; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import lombok.Data; @Entity @Data public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @NotBlank private String username; @NotBlank private String password; @Email @NotBlank private String email; @Enumerated(EnumType.STRING) private Role role; public enum Role { USER, ADMIN } }

3.2. UserRepository


package com.example.userservice.repository; import com.example.userservice.model.User; import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; public interface UserRepository extends JpaRepository<User, Long> { Optional<User> findByUsername(String username); }

3.3. DTO'lar ve Mapper

3.3.1. UserRequest


package com.example.userservice.dto; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import lombok.Data; @Data public class UserRequest { @NotBlank private String username; @NotBlank private String password; @Email @NotBlank private String email; @NotBlank private String role; }

3.3.2. UserResponse


package com.example.userservice.dto; import lombok.Data; @Data public class UserResponse { private Long id; private String username; private String email; private String role; }

3.3.3. UserMapper


package com.example.userservice.mapper; import com.example.userservice.dto.UserRequest; import com.example.userservice.dto.UserResponse; import com.example.userservice.model.User; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @Mapper(componentModel = "spring") public interface UserMapper { @Mapping(target = "role", expression =
"java(User.Role.valueOf(userRequest.getRole().toUpperCase()))") User toEntity(UserRequest userRequest); @Mapping(target = "role", source = "role") UserResponse toResponse(User user); }

3.4. UserService


package com.example.userservice.service; import com.example.userservice.model.User; import com.example.userservice.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class UserService { private final UserRepository userRepository; private final PasswordEncoder passwordEncoder; public User registerUser(User user) { user.setPassword(passwordEncoder.encode(user.getPassword())); return userRepository.save(user); } public User findByUsername(String username) { return userRepository.findByUsername(username).orElse(null); } }

3.5. UserController


package com.example.userservice.controller; import com.example.userservice.dto.UserRequest; import com.example.userservice.dto.UserResponse; import com.example.userservice.mapper.UserMapper; import com.example.userservice.model.User; import com.example.userservice.service.UserService; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/users") @RequiredArgsConstructor public class UserController { private final UserService userService; private final UserMapper userMapper; @PostMapping("/register") public ResponseEntity<UserResponse> registerUser(@Validated
@RequestBody UserRequest userRequest) { User user = userService.registerUser(userMapper.toEntity(userRequest)); return ResponseEntity.ok(userMapper.toResponse(user)); } @GetMapping("/{username}") public ResponseEntity<UserResponse> getUser(@PathVariable String username) { User user = userService.findByUsername(username); if (user == null) { return ResponseEntity.notFound().build(); } return ResponseEntity.ok(userMapper.toResponse(user)); } }

4. Güvenlik Yapılandırması

4.1. SecurityConfig


package com.example.userservice.config; import com.example.userservice.service.UserService; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.
configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.
EnableWebSecurity; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity @RequiredArgsConstructor public class SecurityConfig { private final UserService userService; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http)
throws Exception { http .csrf().disable() .authorizeHttpRequests(authz -> authz .requestMatchers("/users/register").permitAll() .anyRequest().authenticated() ) .oauth2ResourceServer(oauth2 -> oauth2.jwt()); return http.build(); } @Bean public UserDetailsService userDetailsService() { return username -> userService.findByUsername(username); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public AuthenticationManager authenticationManager
(AuthenticationConfiguration authenticationConfiguration) throws Exception { return authenticationConfiguration.getAuthenticationManager(); } }

Sonuç

Bu yapılandırma ile User microservice'i baştan sona tamamladık. MapStruct kullanarak DTO'lar arasında dönüşümleri kolayca gerçekleştirdik ve güvenlik yapılandırmasıyla kullanıcı doğrulama işlemlerini sağladık. Bu yapılandırmayı diğer microservisler için de benzer şekilde uygulayabilirsiniz.


CustomUserDetails,JwtTokenProvider,JwtAuthenticationFilter,JwtAuthenticationToken

1. CustomUserDetails

1.1. CustomUserDetails


package com.example.userservice.security; import com.example.userservice.model.User; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; import java.util.stream.Collectors; import java.util.stream.Stream; public class CustomUserDetails implements UserDetails { private final User user; public CustomUserDetails(User user) { this.user = user; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return Stream.of(new SimpleGrantedAuthority("ROLE_" +
user.getRole().name())) .collect(Collectors.toList()); } @Override public String getPassword() { return user.getPassword(); } @Override public String getUsername() { return user.getUsername(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }

2. JwtTokenProvider

2.1. JwtTokenProvider


package com.example.userservice.security; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Component; import java.util.Date; @Component public class JwtTokenProvider { @Value("${jwt.secret}") private String jwtSecret; @Value("${jwt.expiration}") private Long jwtExpiration; public String generateToken(Authentication authentication) { CustomUserDetails userPrincipal = (CustomUserDetails)
authentication.getPrincipal(); Date now = new Date(); Date expiryDate = new Date(now.getTime() + jwtExpiration); return Jwts.builder() .setSubject(userPrincipal.getUsername()) .setIssuedAt(new Date()) .setExpiration(expiryDate) .signWith(SignatureAlgorithm.HS512, jwtSecret) .compact(); } public String getUserUsernameFromJWT(String token) { Claims claims = Jwts.parser() .setSigningKey(jwtSecret) .parseClaimsJws(token) .getBody(); return claims.getSubject(); } public boolean validateToken(String authToken) { try { Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken); return true; } catch (Exception e) { return false; } } }

3. JwtAuthenticationFilter

3.1. JwtAuthenticationFilter


package com.example.userservice.security; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.web.authentication.
WebAuthenticationDetailsSource; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; @Component @RequiredArgsConstructor public class JwtAuthenticationFilter extends OncePerRequestFilter { private final JwtTokenProvider tokenProvider; private final UserDetailsService userDetailsService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException { String jwt = getJwtFromRequest(request); if (jwt != null && tokenProvider.validateToken(jwt)) { String username = tokenProvider.getUserUsernameFromJWT(jwt); CustomUserDetails userDetails =
(CustomUserDetails) userDetailsService.loadUserByUsername(username); JwtAuthenticationToken authentication =
new JwtAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource()
.buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authentication); } filterChain.doFilter(request, response); } private String getJwtFromRequest(HttpServletRequest request) { String bearerToken = request.getHeader("Authorization"); if (bearerToken != null && bearerToken.startsWith("Bearer ")) { return bearerToken.substring(7); } return null; } }

4. JwtAuthenticationToken

4.1. JwtAuthenticationToken


package com.example.userservice.security; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import java.util.Collection; public class JwtAuthenticationToken extends AbstractAuthenticationToken { private final Object principal; public JwtAuthenticationToken(Object principal, Object credentials,
Collection<? extends GrantedAuthority> authorities) { super(authorities); this.principal = principal; setAuthenticated(true); } @Override public Object getCredentials() { return null; } @Override public Object getPrincipal() { return this.principal; } }

Tam Proje Kodu

Projenin tamamı aşağıda verilmiştir. Her bir bileşen yukarıda detaylandırılmıştır ve aşağıda proje dizin yapısında belirtilmiştir.


user-service │ ├── pom.xml │ ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ └── example │ │ │ └── userservice │ │ │ ├── UserServiceApplication.java │ │ │ ├── controller │ │ │ │ └── UserController.java │ │ │ ├── dto │ │ │ │ ├── UserRequest.java │ │ │ │ └── UserResponse.java │ │ │ ├── mapper │ │ │ │ └── UserMapper.java │ │ │ ├── model │ │ │ │ └── User.java │ │ │ ├── repository │ │ │ │ └── UserRepository.java │ │ │ ├── security │ │ │ │ ├── CustomUserDetails.java │ │ │ │ ├── JwtAuthenticationFilter.java │ │ │ │ ├── JwtAuthenticationToken.java │ │ │ │ └── JwtTokenProvider.java │ │ │ ├── config │ │ │ │ └── SecurityConfig.java │ │ │ └── service │ │ │ └── UserService.java │ │ └── resources │ │ ├── application.yml │ │ └── data.sql └── src ├── test └── java └── com └── example └── userservice └── UserServiceApplicationTests.java

UserServiceApplication.java


package com.example.userservice; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class UserServiceApplication { public static void main(String[] args) { SpringApplication.run(UserServiceApplication.class, args); } }

Bu yapılandırma ile User microservice'ini tamamlamış olduk. Her bileşen bağımsız olarak çalışır ve JWT ile güvenli bir kimlik doğrulama sağlar. MapStruct kullanarak DTO'lar arasındaki dönüşümleri de sağladık. Bu yapılandırmayı diğer microservisler için de benzer şekilde uygulayabilirsiniz.


Junit5 ve Mocikto ile birim ve entegrasyon testlerini de yaz

Unit ve Entegrasyon Testleri

JUnit 5 ve Mockito kullanarak User microservice'i için birim ve entegrasyon testleri yazalım.

1. Birim Testleri

1.1. UserServiceTest


package com.example.userservice.service; import com.example.userservice.model.User; import com.example.userservice.repository.UserRepository; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.security.crypto.password.PasswordEncoder; import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) public class UserServiceTest { @Mock private UserRepository userRepository; @Mock private PasswordEncoder passwordEncoder; @InjectMocks private UserService userService; @Test void testRegisterUser() { User user = new User(); user.setUsername("testuser"); user.setPassword("password"); when(passwordEncoder.encode(anyString())).thenReturn("encodedPassword"); when(userRepository.save(any(User.class))).thenReturn(user); User savedUser = userService.registerUser(user); assertNotNull(savedUser); assertEquals("testuser", savedUser.getUsername()); verify(passwordEncoder, times(1)).encode("password"); verify(userRepository, times(1)).save(user); } @Test void testFindByUsername() { User user = new User(); user.setUsername("testuser"); when(userRepository.findByUsername("testuser")).
thenReturn(Optional.of(user)); User foundUser = userService.findByUsername("testuser"); assertNotNull(foundUser); assertEquals("testuser", foundUser.getUsername()); verify(userRepository, times(1)).findByUsername("testuser"); } }

2. Entegrasyon Testleri

2.1. UserControllerIntegrationTest


package com.example.userservice.controller; import com.example.userservice.dto.UserRequest; import com.example.userservice.dto.UserResponse; import com.example.userservice.model.User; import com.example.userservice.repository.UserRepository; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.
AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import java.util.Optional; import static org.springframework.test.web.servlet.request.
MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.
MockMvcResultMatchers.*; @ExtendWith(SpringExtension.class) @SpringBootTest @AutoConfigureMockMvc public class UserControllerIntegrationTest { @Autowired private MockMvc mockMvc; @Autowired private UserRepository userRepository; @Autowired private ObjectMapper objectMapper; @BeforeEach void setUp() { userRepository.deleteAll(); } @Test void testRegisterUser() throws Exception { UserRequest userRequest = new UserRequest(); userRequest.setUsername("testuser"); userRequest.setPassword("password"); userRequest.setEmail("testuser@example.com"); userRequest.setRole("USER"); mockMvc.perform(post("/users/register") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(userRequest))) .andExpect(status().isOk()) .andExpect(jsonPath("$.username").value("testuser")) .andExpect(jsonPath("$.email").value("testuser@example.com")); } @Test void testGetUser() throws Exception { User user = new User(); user.setUsername("testuser"); user.setPassword("password"); user.setEmail("testuser@example.com"); user.setRole(User.Role.USER); userRepository.save(user); mockMvc.perform(get("/users/testuser") .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.username").value("testuser")) .andExpect(jsonPath("$.email").value("testuser@example.com")); } @Test void testGetUserNotFound() throws Exception { mockMvc.perform(get("/users/nonexistentuser") .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } }

3. pom.xml Güncellemesi

Test kütüphanelerini eklemek için pom.xml dosyasına gerekli bağımlılıkları ekleyin.


<dependencies> <!-- Other dependencies --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-junit-jupiter</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> </dependencies>

4. Uygulama Testleri İçin application.yml

Test ortamı için gerekli yapılandırmaları da ekleyin.


spring: datasource: url: jdbc:postgresql://localhost:5432/usersdb_test username: postgres password: password driver-class-name: org.postgresql.Driver jpa: hibernate: ddl-auto: create-drop show-sql: true

Sonuç

Yukarıdaki birim ve entegrasyon testleri, User microservice'in farklı katmanlarını kapsar. Bu testler, servis ve kontrolör katmanlarının beklenen şekilde çalıştığını doğrular. JUnit 5 ve Mockito kullanarak bu testleri yazmak, kodun doğruluğunu ve güvenilirliğini artırır. Entegrasyon testleri ise uygulamanın çeşitli bileşenlerinin birlikte nasıl çalıştığını test eder. Bu yapı, microservice'in sağlam ve hatasız olmasını sağlar.


Bu servise authontication service desek daha doğru olmaz mıydı? Veya başka ne isim verebiliriz?

Evet, bu servis, kullanıcı kaydı, kimlik doğrulama ve yetkilendirme işlemlerini yönettiği için "Authentication Service" (Kimlik Doğrulama Servisi) olarak adlandırmak daha uygun olabilir. Alternatif olarak aşağıdaki isimler de uygun olabilir:
  1. Identity Service (Kimlik Servisi): Kullanıcı kimlik bilgileri ve doğrulama süreçlerini yönetir.
  2. Auth Service (Kısaltılmış Kimlik Doğrulama Servisi): Kimlik doğrulama ve yetkilendirme işlemlerini kapsar.
  3. User Management Service (Kullanıcı Yönetim Servisi): Kullanıcı bilgilerini ve kimlik doğrulama işlemlerini kapsar.

Bu isimlendirmelerden herhangi biri, servisin amacını daha iyi yansıtabilir.

Rastgele İçerik

© tüm hakları saklıdır
made with by templateszoo