JavaRush /جاوا بلاگ /Random-SD /Mapstruct ڇا آهي ۽ اسپرنگ بوٽ ايپليڪيشنن ۾ يونٽ جي جاچ لا...

Mapstruct ڇا آهي ۽ اسپرنگ بوٽ ايپليڪيشنن ۾ يونٽ جي جاچ لاءِ ان کي صحيح طريقي سان ترتيب ڏيڻ

گروپ ۾ شايع ٿيل

پس منظر

هيلو هرڪو، منهنجا پيارا دوست ۽ پڙهندڙ! ان کان اڳ جو اسان مضمون لکون، ٿورو پس منظر... مون تازو ئي Mapstruct لائبريري سان ڪم ڪندي هڪ مسئلو پيش آيو ، جنهن کي مون پنهنجي ٽيليگرام چينل ۾ مختصر طور بيان ڪيو آهي . تبصرن ۾، پوسٽ سان مسئلو حل ڪيو ويو؛ پوئين منصوبي کان منهنجي ساٿي هن سان مدد ڪئي. Mapstruct ڇا آهي ۽ اسپرنگ بوٽ ايپليڪيشنن ۾ يونٽ جي جاچ لاءِ ان کي صحيح طريقي سان ترتيب ڏيڻ.  حصو 1 - 1ان کان پوء، مون هن موضوع تي هڪ مضمون لکڻ جو فيصلو ڪيو، پر يقينن اسان هڪ تنگ نظر نه ڪنداسين ۽ پهرين رفتار کي وڌائڻ جي ڪوشش ڪنداسين، سمجھو ته Mapstruct ڇا آهي ۽ ڇو ضروري آهي، ۽ هڪ حقيقي مثال استعمال ڪندي. اڳ ۾ پيدا ٿيندڙ صورتحال جو تجزيو ڪيو ۽ ان کي ڪيئن حل ڪجي. تنهن ڪري، آئون مشق ۾ هر شيء کي تجربو ڪرڻ لاء آرٽيڪل پڙهڻ سان متوازي طور تي سڀني حسابن کي ڪرڻ جي صلاح ڏيان ٿو. شروع ڪرڻ کان اڳ، منهنجي ٽيليگرام چينل کي سبسڪرائب ڪيو ، مان اتي پنهنجون سرگرميون گڏ ڪريان ٿو، جاوا ۽ آئي ٽي ۾ ترقي بابت سوچون لکان ٿو. رڪنيت حاصل ڪئي؟ زبردست! چڱو، هاڻي اچو ته هلون!

نقشو، سوال؟

فاسٽ ٽائپ-سيف بين ميپنگ لاءِ ڪوڊ جنريٽر. اسان جو پهريون ڪم اهو معلوم ڪرڻ آهي ته Mapstruct ڇا آهي ۽ اسان کي ان جي ضرورت ڇو آهي. عام طور تي، توهان ان بابت پڙهي سگهو ٿا سرڪاري ويب سائيٽ تي. سائيٽ جي مکيه صفحي تي سوالن جا ٽي جواب آھن: اھو ڇا آھي؟ ڇا جي لاءِ؟ ڪيئن؟ اسان هن کي پڻ ڪرڻ جي ڪوشش ڪنداسين:

هي ڇا آهي؟

Mapstruct هڪ لائبريري آهي جيڪا نقشي ٺاهڻ ۾ مدد ڪري ٿي (نقشو، عام طور تي، اهو آهي جيڪو اهي هميشه چوندا آهن: نقشو، نقشو، وغيره) ڪجهه ادارن جي شين کي ٻين ادارن جي شين ۾ ٺاهيل ڪوڊ استعمال ڪندي ٺاهيل ڪوڊ جي بنياد تي ترتيبن جي بنياد تي بيان ڪيل آهي.

ڇا جي لاءِ؟

گھڻي ڀاڱي لاءِ، اسان گھڻن پرت واري ايپليڪيشنن کي ترقي ڪريون ٿا (ڊيٽابيس سان ڪم ڪرڻ لاءِ ھڪ پرت، ڪاروباري منطق جي ھڪڙي پرت، ھڪ پرت، ٻاھرين دنيا سان ايپليڪيشن جي رابطي لاءِ) ۽ ھر پرت وٽ پنھنجيون شيون آھن ڊيٽا کي محفوظ ڪرڻ ۽ پروسيس ڪرڻ لاءِ. . ۽ هي ڊيٽا هڪ پرت کان ٻئي پرت کي منتقل ڪرڻ جي ذريعي منتقل ڪرڻ جي ضرورت آهي. انهن لاءِ جن هن طريقي سان ڪم نه ڪيو آهي، اهو لڳي سگهي ٿو ٿورڙو پيچيده. مثال طور، اسان وٽ ھڪڙو ادارو آھي شاگردن جي ڊيٽابيس لاءِ. جڏهن هن اداري جو ڊيٽا ڪاروباري منطق (سروسز) پرت ڏانهن وڃي ٿو، اسان کي ڊيٽا کي شاگردن جي طبقي مان StudentModel ڪلاس ۾ منتقل ڪرڻ جي ضرورت آهي. اڳيون، ڪاروباري منطق سان سڀني ٺاهه کان پوء، ڊيٽا کي ٻاهر ڇڏڻ جي ضرورت آهي. ۽ ان لاءِ اسان وٽ آھي StudentDto ڪلاس. يقينن، اسان کي اسٽوڊنٽ ماڊل ڪلاس کان StudentDto تائين ڊيٽا منتقل ڪرڻ جي ضرورت آهي. هر دفعي هٿ سان لکڻ وارا طريقا جيڪي منتقل ڪيا ويندا محنت ڪندڙ آهن. ان سان گڏ هي ڪوڊ بيس ۾ اضافي ڪوڊ آهي جنهن کي برقرار رکڻ جي ضرورت آهي. توهان هڪ غلطي ڪري سگهو ٿا. ۽ Mapstruct اھڙا طريقا ٺاھڻ واري مرحلي ۾ ٺاھي ٿو ۽ انھن کي پيدا ڪيل ذريعن ۾ ذخيرو ڪري ٿو.

ڪيئن؟

تشريح استعمال ڪندي. اسان کي صرف هڪ تشريح ٺاهڻ جي ضرورت آهي جنهن ۾ هڪ مکيه Mapper تشريح آهي جيڪا لائبريري کي ٻڌائي ٿي ته هن انٽرفيس ۾ طريقا استعمال ڪري سگهجن ٿا هڪ اعتراض کان ٻئي ۾ ترجمو ڪرڻ لاءِ. جيئن مون اڳ ۾ شاگردن جي باري ۾ چيو آهي، اسان جي صورت ۾ اهو ٿيندو StudentMapper انٽرفيس، جنهن ۾ ڊيٽا کي هڪ پرت کان ٻئي پرت منتقل ڪرڻ جا ڪيترائي طريقا هوندا:
public class Student {
   private Long id;
   private String firstName;
   private String lastName;
   private Integer age;
}

public class StudentDTO {
   private Long id;
   private String firstName;
   private String lastName;
   private Integer age;
}

public class StudentModel {
   private Long id;
   private String firstName;
   private String lastName;
   private Integer age;
}
انهن طبقن لاءِ اسان هڪ ميپر ٺاهيندا آهيون (هتي اهو آهي جيڪو اسان انٽرفيس کي سڏينداسين، جيڪو بيان ڪري ٿو ته اسان ڇا منتقل ڪرڻ چاهيون ٿا ۽ ڪٿي):
@Mapper
public interface StudentMapper {
   StudentModel toModel(StudentDTO dto);
   Student toEntity(StudentModel model);
   StudentModel toModel(Student entity);
   StudentDTO toDto(StudentModel model);
}
هن طريقي جي خوبي اها آهي ته جيڪڏهن فيلڊ جا نالا ۽ قسم مختلف طبقن ۾ هڪجهڙا آهن (جيئن اسان جي صورت ۾)، ته پوءِ Mapstruct لاءِ سيٽنگون ڪافي هونديون آهن ضروري عمل درآمد ڪرڻ لاءِ جيڪو اسٽوڊنٽ ميپر انٽرفيس جي بنياد تي مرتب ڪرڻ واري مرحلي ۾، جيڪو ترجمو ڪندو. تنهنڪري اهو اڳ ۾ ئي واضح ٿي چڪو آهي، صحيح؟ اچو ته اڳتي وڌون ۽ اسپرنگ بوٽ ايپليڪيشن ۾ ڪم جو تجزيو ڪرڻ لاءِ هڪ حقيقي مثال استعمال ڪريون.

اسپرنگ بوٽ ۽ Mapstruct ڪم ڪرڻ جو هڪ مثال

پهرين شيء جيڪا اسان کي ضرورت آهي هڪ اسپرنگ بوٽ پروجيڪٽ ٺاهڻ ۽ ان ۾ Mapstruct شامل ڪرڻ آهي. هن معاملي لاء، مون وٽ هڪ تنظيم آهي GitHub ۾ ٽيمپليٽس سان گڏ ذخيرو لاءِ ۽ اسپرنگ بوٽ جي شروعات انهن مان هڪ آهي. ان جي بنياد تي، اسان ھڪڙو نئون منصوبو ٺاھيو: Mapstruct ڇا آهي ۽ اسپرنگ بوٽ ايپليڪيشنن ۾ يونٽ جي جاچ لاءِ ان کي صحيح طريقي سان ترتيب ڏيڻ.  حصو 1 - 2اڳيون، اسان پروجيڪٽ حاصل ڪندا آھيون . ها، دوستو، جيڪڏهن توهان کي اهو پروجيڪٽ ڪارائتو لڳي ته هڪ اسٽار ڏيو ، پوء مون کي خبر پئجي ويندي ته مان اهو بيڪار نه ڪري رهيو آهيان. هن منصوبي ۾، اسان هڪ صورتحال ظاهر ڪنداسين جيڪا مون ڪم تي حاصل ڪئي ۽ منهنجي ٽيليگرام چينل تي هڪ پوسٽ ۾ بيان ڪيو . مان مختصر طور تي انھن لاءِ صورتحال بيان ڪندس جيڪي ڄاڻ ۾ نه آھن: جڏھن اسان ميپرز لاءِ ٽيسٽ لکون ٿا (اھو آھي، انھن انٽرفيس جي عملن لاءِ جن بابت اسان اڳ ۾ ڳالھايو آھي)، اسان چاھيون ٿا ته ٽيسٽ جلد کان جلد گذري وڃن. ميپرز سان گڏ سڀ کان آسان اختيار آھي SpringBootTest تشريح استعمال ڪرڻ جڏھن ٽيسٽ ھلائيندي، جيڪو اسپرنگ بوٽ ايپليڪيشن جي پوري ApplicationContext کي کڻندو ۽ ٽيسٽ اندر ٽيسٽ لاءِ گھربل ميپر کي انجيڪشن ڪندو. پر هي اختيار وسيع آهي ۽ گهڻو وقت وٺندو آهي، تنهنڪري اهو اسان لاء مناسب ناهي. اسان کي هڪ يونٽ ٽيسٽ لکڻ جي ضرورت آهي جيڪا صرف مطلوب ميپر ٺاهي ٿي ۽ چيڪ ڪري ٿي ته ان جا طريقا بلڪل ڪم ڪن ٿا جيئن اسان توقع ڪندا آهيون. توهان کي تيز هلائڻ لاءِ ٽيسٽن جي ضرورت ڇو آهي؟ جيڪڏهن ٽيسٽ هڪ ڊگهو وقت وٺي، اهو سڄي ترقي جي عمل کي سست ڪري ٿو. جيستائين نئين ڪوڊ تي ٽيسٽ پاس نه ٿيندي، اهو ڪوڊ صحيح سمجهي نه ٿو سگهجي ۽ جانچ لاءِ نه ورتو ويندو، جنهن جو مطلب آهي ته اهو پيداوار ۾ نه ورتو ويندو ۽ جنهن جو مطلب آهي ته ڊولپر ڪم مڪمل نه ڪيو آهي. اهو لڳي ٿو، هڪ لائبريري لاء هڪ امتحان ڇو لکندو آهي جنهن جو آپريشن شڪ کان ٻاهر آهي؟ ۽ اڃان تائين اسان کي هڪ ٽيسٽ لکڻ جي ضرورت آهي، ڇاڪاڻ ته اسان جاچ ڪري رهيا آهيون ته اسان ميپر کي ڪيئن صحيح نموني بيان ڪيو آهي ۽ ڇا اهو اهو ڪري ٿو جيڪو اسان جي توقع آهي. سڀ کان پهريان، اسان جي ڪم کي آسان ڪرڻ لاء، اچو ته Lombok کي اسان جي پروجيڪٽ ۾ شامل ڪريون pom.xml تي هڪ ٻيو انحصار شامل ڪندي:
<dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
   <scope>provided</scope>
</dependency>
اسان جي پروجيڪٽ ۾، اسان کي ماڊل ڪلاسن (جيڪي ڪاروباري منطق سان ڪم ڪرڻ لاءِ استعمال ڪيا ويندا آهن) مان ڊي ٽي او ڪلاسن ۾ منتقل ڪرڻ جي ضرورت پوندي، جن کي اسين ٻاهرئين دنيا سان رابطو ڪرڻ لاءِ استعمال ڪندا آهيون. اسان جي سادي ورزن ۾، اسان اهو فرض ڪنداسين ته فيلڊ تبديل نه ڪندا آهن ۽ اسان جا نقشا سادو هوندا. پر، جيڪڏهن ڪا خواهش آهي، ته اهو ممڪن ٿيندو ته هڪ وڌيڪ تفصيلي مضمون لکڻ لاءِ ته Mapstruct سان ڪيئن ڪم ڪجي، ان کي ڪيئن ترتيب ڪجي، ۽ ان جي فائدن مان ڪيئن فائدو ورتو وڃي. پر پوءِ به، هي مضمون ڪافي ڊگهو ٿيندو. اچو ته چون ٿا ته اسان وٽ هڪ شاگرد آهي ليڪچرن ۽ ليڪچررن جي فهرست سان جيڪو هو شرڪت ڪري ٿو. اچو ته هڪ ماڊل پيڪيج ٺاهي . انهي جي بنياد تي، اسان هڪ سادي نموني ٺاهي سگهون ٿا:
package com.github.romankh3.templaterepository.springboot.dto;

import lombok.Data;

import java.util.List;

@Data
public class StudentDTO {

   private Long id;

   private String name;

   private List<LectureDTO> lectures;

   private List<LecturerDTO> lecturers;
}
هن جا ليڪچر
package com.github.romankh3.templaterepository.springboot.dto;

import lombok.Data;

@Data
public class LectureDTO {

   private Long id;

   private String name;
}
۽ ليڪچررز
package com.github.romankh3.templaterepository.springboot.dto;

import lombok.Data;

@Data
public class LecturerDTO {

   private Long id;

   private String name;
}
۽ ماڊل پيڪيج جي اڳيان هڪ dto پيڪيج ٺاهيو :
package com.github.romankh3.templaterepository.springboot.dto;

import lombok.Data;

import java.util.List;

@Data
public class StudentDTO {

   private Long id;

   private String name;

   private List<LectureDTO> lectures;

   private List<LecturerDTO> lecturers;
}
ليڪچر
package com.github.romankh3.templaterepository.springboot.dto;

import lombok.Data;

@Data
public class LectureDTO {

   private Long id;

   private String name;
}
۽ ليڪچررز
package com.github.romankh3.templaterepository.springboot.dto;

import lombok.Data;

@Data
public class LecturerDTO {

   private Long id;

   private String name;
}
ھاڻي اچو ھڪڙو نقشو ٺاھيو جيڪو ليڪچر ماڊلز جي مجموعي کي ڊي ٽي او ليڪچرن جي مجموعي ۾ ترجمو ڪندو. ڪرڻ جو پهريون ڪم آهي Mapstruct شامل ڪريو پروجيڪٽ ۾. هن کي ڪرڻ لاء، اسان انهن جي سرڪاري ويب سائيٽ استعمال ڪنداسين ، هر شي بيان ڪيل آهي. اھو آھي، اسان کي پنھنجي ياداشت ۾ ھڪڙو انحصار ۽ ھڪڙو پلگ ان شامل ڪرڻ جي ضرورت آھي (جيڪڏھن توھان وٽ سوال آھي ته ميموري ڇا آھي، ھتي وڃو، آرٽيڪل1 ۽ آرٽيڪل2 ):
<dependency>
   <groupId>org.mapstruct</groupId>
   <artifactId>mapstruct</artifactId>
   <version>1.4.2.Final</version>
</dependency>
۽ ميموري ۾ <build/> block. جيڪو اسان اڃا تائين نه ڪيو آهي:
<build>
   <plugins>
       <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>
           <version>3.5.1</version>
           <configuration>
               <source>1.8</source>
               <target>1.8</target>
               <annotationProcessorPaths>
                   <path>
                       <groupId>org.mapstruct</groupId>
                       <artifactId>mapstruct-processor</artifactId>
                       <version>1.4.2.Final</version>
                   </path>
               </annotationProcessorPaths>
           </configuration>
       </plugin>
   </plugins>
</build>
اڳيون، اچو ته dto ۽ ماڊل جي اڳيان هڪ ميپر پيڪيج ٺاهي . ڪلاسن جي بنياد تي جيڪي اسان اڳ ۾ ڏيکاريا هئا، توهان کي پنج وڌيڪ نقشا ٺاهڻ جي ضرورت پوندي:
  • Mapper LectureModel <-> LectureDTO
  • Mapper List<LectureModel> <-> List<LectureDTO>
  • ميپر ليڪچرر ماڊل <-> ليڪچرر ڊي ٽي او
  • Mapper List<LecturerModel> <-> List<LecturerDTO>
  • Mapper StudentModel <-> StudentDTO
وڃ:

ليڪچر ميپر

package com.github.romankh3.templaterepository.springboot.mapper;

import com.github.romankh3.templaterepository.springboot.dto.LectureDTO;
import com.github.romankh3.templaterepository.springboot.dto.LecturerDTO;
import com.github.romankh3.templaterepository.springboot.model.LectureModel;
import org.mapstruct.Mapper;

@Mapper(componentModel = "spring")
public interface LectureMapper {
   LectureDTO toDTO(LectureModel model);

   LectureModel toModel(LecturerDTO dto);
}

LectureListMapper

package com.github.romankh3.templaterepository.springboot.mapper;

import com.github.romankh3.templaterepository.springboot.dto.LectureDTO;
import com.github.romankh3.templaterepository.springboot.dto.LectureDTO;
import com.github.romankh3.templaterepository.springboot.model.LectureModel;
import org.mapstruct.Mapper;

import java.util.List;

@Mapper(componentModel = "spring", uses = LectureMapper.class)
public interface LectureListMapper {
   List<LectureModel> toModelList(List<LectureDTO> dtos);
   List<LectureDTO> toDTOList(List<LectureModel> models);
}

ليڪچرر ميپر

package com.github.romankh3.templaterepository.springboot.mapper;

import com.github.romankh3.templaterepository.springboot.dto.LectureDTO;
import com.github.romankh3.templaterepository.springboot.model.LectureModel;
import org.mapstruct.Mapper;

@Mapper(componentModel = "spring")
public interface LectureMapper {
   LectureDTO toDTO(LectureModel model);

   LectureModel toModel(LectureDTO dto);
}

ليڪچرر لسٽ ميپر

package com.github.romankh3.templaterepository.springboot.mapper;

import com.github.romankh3.templaterepository.springboot.dto.LecturerDTO;
import com.github.romankh3.templaterepository.springboot.model.LecturerModel;
import org.mapstruct.Mapper;

import java.util.List;

@Mapper(componentModel = "spring", uses = LecturerMapper.class)
public interface LecturerListMapper {
   List<LecturerModel> toModelList(List<LecturerDTO> dloList);
   List<LecturerDTO> toDTOList(List<LecturerModel> modelList);
}

شاگرد ميپر

package com.github.romankh3.templaterepository.springboot.mapper;

import com.github.romankh3.templaterepository.springboot.dto.StudentDTO;
import com.github.romankh3.templaterepository.springboot.model.StudentModel;
import org.mapstruct.Mapper;

@Mapper(componentModel = "spring", uses = {LectureListMapper.class, LecturerListMapper.class})
public interface StudentMapper {
   StudentDTO toDTO(StudentModel model);
   StudentModel toModel(StudentDTO dto);
}
اهو الڳ الڳ ياد رکڻ گهرجي ته نقشن ۾ اسان ٻين نقشن ڏانهن اشارو ڪندا آهيون. اهو ميپر جي تشريح ۾ استعمال ٿيل فيلڊ ذريعي ڪيو ويندو آهي، جيئن StudentMapper ۾ ڪيو ويندو آهي:
@Mapper(componentModel = "spring", uses = {LectureListMapper.class, LecturerListMapper.class})
هتي اسان ليڪچرن جي لسٽ ۽ ليڪچررن جي فهرست کي صحيح طرح سان نقشي ڪرڻ لاءِ ٻه ميپر استعمال ڪريون ٿا. هاڻي اسان کي اسان جي ڪوڊ گڏ ڪرڻ جي ضرورت آهي ۽ ڏسو ته اتي ڇا آهي ۽ ڪيئن. اهو استعمال ڪري سگهجي ٿو mvn clean compile حڪم . پر، جيئن اهو نڪتو، جڏهن اسان جي نقشن جي نقشي تي عمل درآمد ٺاهيندي، نقشي تي عمل درآمد فيلڊ کي اوور رائٽ نه ڪيو. ڇو؟ اهو ظاهر ٿيو ته اهو ممڪن ناهي ته Lombok کان ڊيٽا جي تشريح کي کڻڻ. ۽ ڪجهه ٿيڻو هو... تنهن ڪري، اسان وٽ مضمون ۾ هڪ نئون سيڪشن آهي.

Lombok ۽ Mapstruct کي ڳنڍڻ

ڪجهه منٽن جي ڳولا کان پوء، اهو ظاهر ٿيو ته اسان کي Lombok ۽ Mapstruct کي هڪ خاص طريقي سان ڳنڍڻ جي ضرورت آهي. ھن بابت ڄاڻ آھي Mapstruct جي دستاويزن ۾ . Mapstruct مان ڊولپرز پاران تجويز ڪيل مثال کي جانچڻ کان پوء، اچو ته اسان جي pom.xml کي اپڊيٽ ڪريون: اچو ته الڳ ورزن شامل ڪريون:
​​<properties>
   <org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
   <lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
</properties>
اچو ته شامل ڪريو غائب انحصار:
<dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok-mapstruct-binding</artifactId>
   <version>${lombok-mapstruct-binding.version}</version>
</dependency>
۽ اچو ته اسان جي مرتب ڪندڙ پلگ ان کي تازه ڪاري ڪريون ته جيئن اهو Lombok ۽ Mapstruct کي ڳنڍي سگهي:
<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-compiler-plugin</artifactId>
   <version>3.5.1</version>
   <configuration>
       <source>1.8</source>
       <target>1.8</target>
       <annotationProcessorPaths>
           <path>
               <groupId>org.mapstruct</groupId>
               <artifactId>mapstruct-processor</artifactId>
               <version>${org.mapstruct.version}</version>
           </path>
           <path>
               <groupId>org.projectlombok</groupId>
               <artifactId>lombok</artifactId>
               <version>${lombok.version}</version>
           </path>
           <path>
               <groupId>org.projectlombok</groupId>
               <artifactId>lombok-mapstruct-binding</artifactId>
               <version>${lombok-mapstruct-binding.version}</version>
           </path>
       </annotationProcessorPaths>
   </configuration>
</plugin>
ان کان پوء، سڀڪنھن شيء کي ڪم ڪرڻ گهرجي. اچو ته اسان جي منصوبي کي ٻيهر ترتيب ڏيو. پر توهان ڪٿي ڳولي سگهو ٿا ڪلاس جيڪي Mapstruct ٺاهيا آهن؟ اهي generated-sources ۾ آهن: ${projectDir}/target/generated-sources/annotations/ Mapstruct ڇا آهي ۽ اسپرنگ بوٽ ايپليڪيشنن ۾ يونٽ جي جاچ لاءِ ان کي صحيح طريقي سان ترتيب ڏيڻ.  حصو 1 - 3 هاڻي جڏهن اسان Mapstruct پوسٽ مان منهنجي مايوسي کي محسوس ڪرڻ لاءِ تيار آهيون، اچو ته ڪوشش ڪريون ميپرز لاءِ ٽيسٽون ٺاهڻ جي.

اسان اسان جي نقشن لاء ٽيسٽ لکندا آهيون

مان ھڪڙو تڪڙو ۽ سادو ٽيسٽ ٺاھيندس جيڪو ھڪڙي ھڪڙي ماپرز کي جانچيندو ان صورت ۾ جتي اسان انٽيگريشن ٽيسٽ ٺاھي رھيا آھيون ۽ ان جي مڪمل ٿيڻ جي وقت بابت پريشان نه ڪريو:

ليڪچر ميپر ٽيسٽ

package com.github.romankh3.templaterepository.springboot.mapper;

import com.github.romankh3.templaterepository.springboot.dto.LectureDTO;
import com.github.romankh3.templaterepository.springboot.model.LectureModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class LectureMapperTest {

   @Autowired
   private LectureMapper mapperUnderTest;

   @Test
   void shouldProperlyMapModelToDto() {
       //given
       LectureModel model = new LectureModel();
       model.setId(11L);
       model.setName("lecture name");

       //when
       LectureDTO dto = mapperUnderTest.toDTO(model);

       //then
       Assertions.assertNotNull(dto);
       Assertions.assertEquals(model.getId(), dto.getId());
       Assertions.assertEquals(model.getName(), dto.getName());
   }

   @Test
   void shouldProperlyMapDtoToModel() {
       //given
       LectureDTO dto = new LectureDTO();
       dto.setId(11L);
       dto.setName("lecture name");

       //when
       LectureModel model = mapperUnderTest.toModel(dto);

       //then
       Assertions.assertNotNull(model);
       Assertions.assertEquals(dto.getId(), model.getId());
       Assertions.assertEquals(dto.getName(), model.getName());
   }
}
هتي، SpringBootTest تشريح کي استعمال ڪندي، اسان سڄي ايپليڪيشن کي شروع ڪريون ٿا ۽ ان مان، آٽو وائرڊ تشريح استعمال ڪندي، اسان ڪلاس ڪڍيون ٿا جيڪو اسان کي جانچ لاءِ گهربل آهي. رفتار جي نقطي نظر کان ۽ امتحان لکڻ جي آسانيء سان، هي تمام سٺو آهي. امتحان ڪاميابي سان گذري ٿو، سڀ ڪجھ ٺيڪ آهي. پر اسان ٻئي طرف وينداسين ۽ هڪ ميپر لاءِ يونٽ ٽيسٽ لکنداسين، مثال طور، LectureListMapper...
package com.github.romankh3.templaterepository.springboot.mapper;

import com.github.romankh3.templaterepository.springboot.dto.LectureDTO;
import com.github.romankh3.templaterepository.springboot.model.LectureModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.Collections;
import java.util.List;

class LectureListMapperTest {

   private final LectureListMapper lectureListMapper = new LectureListMapperImpl();

   @Test
   void shouldProperlyMapListDtosToListModels() {
       //given
       LectureDTO dto = new LectureDTO();
       dto.setId(12L);
       dto.setName("I'm BATMAN!");

       List<LectureDTO> dtos = Collections.singletonList(dto);

       //when
       List<LectureModel> models = lectureListMapper.toModelList(dtos);

       //then
       Assertions.assertNotNull(models);
       Assertions.assertEquals(1, models.size());
       Assertions.assertEquals(dto.getId(), models.get(0).getId());
       Assertions.assertEquals(dto.getName(), models.get(0).getName());
   }
}
جيئن ته اهي عمل جيڪي Mapstruct ٺاهي ٿو اسان جي پروجيڪٽ جي ساڳي طبقي ۾ آهن، اسان انهن کي آساني سان اسان جي تجربن ۾ استعمال ڪري سگهون ٿا. هر شيءِ سٺي لڳندي آهي - ڪابه تشريح ناهي، اسان اهو طبقو ٺاهيندا آهيون جنهن جي اسان کي ضرورت آهي سادو طريقي سان ۽ بس. پر جڏهن اسان ٽيسٽ هلائينداسين، اسان سمجھنداسين ته اهو حادثو ٿيندو ۽ ڪنسول ۾ هڪ NullPointerException هوندو... اهو ئي سبب آهي ته LectureListMapper ميپر جو نفاذ هن طرح نظر اچي ٿو:
package com.github.romankh3.templaterepository.springboot.mapper;

import com.github.romankh3.templaterepository.springboot.dto.LectureDTO;
import com.github.romankh3.templaterepository.springboot.model.LectureModel;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Generated(
   value = "org.mapstruct.ap.MappingProcessor",
   date = "2021-12-09T21:46:12+0300",
   comments = "version: 1.4.2.Final, compiler: javac, environment: Java 15.0.2 (N/A)"
)
@Component
public class LectureListMapperImpl implements LectureListMapper {

   @Autowired
   private LectureMapper lectureMapper;

   @Override
   public List<LectureModel> toModelList(List<LectureDTO> dtos) {
       if ( dtos == null ) {
           return null;
       }

       List<LectureModel> list = new ArrayList<LectureModel>( dtos.size() );
       for ( LectureDTO lectureDTO : dtos ) {
           list.add( lectureMapper.toModel( lectureDTO ) );
       }

       return list;
   }

   @Override
   public List<LectureDTO> toDTOList(List<LectureModel> models) {
       if ( models == null ) {
           return null;
       }

       List<LectureDTO> list = new ArrayList<LectureDTO>( models.size() );
       for ( LectureModel lectureModel : models ) {
           list.add( lectureMapper.toDTO( lectureModel ) );
       }

       return list;
   }
}
جيڪڏهن اسان ڏسون ٿا NPE (مختصر لاء NullPointerException)، اسان ان کي lectureMapper variable مان حاصل ڪريون ٿا ، جيڪو ظاهر ٿئي ٿو ته شروعات نه ڪئي وئي آهي. پر اسان جي عمل ۾ اسان وٽ ھڪڙو ٺاھيندڙ نه آھي جنھن سان اسين متغير کي شروع ڪري سگھون. اهو ئي سبب آهي ته Mapstruct هن طريقي سان ميپر کي لاڳو ڪيو! بهار ۾، توھان ڪيترن ئي طريقن سان ڪلاسن ۾ لوبيا شامل ڪري سگھو ٿا، توھان انھن کي فيلڊ ذريعي انجيڪشن ڪري سگھوٿا آٽو وائرڊ اينوٽيشن سان گڏ، جيئن مٿي ڪيو ويو آھي، يا توھان انھن کي ٺاھيندڙ جي ذريعي انجيڪشن ڪري سگھو ٿا. مون پاڻ کي ڪم تي اهڙي مشڪل صورتحال ۾ محسوس ڪيو جڏهن مون کي امتحان جي عمل جي وقت کي بهتر ڪرڻ جي ضرورت هئي. مون سوچيو ته ان بابت ڪجهه به نه ٿو ڪري سگهجي ۽ پنهنجي ٽيليگرام چينل تي پنهنجو درد اُڇلائي ڇڏيم. ۽ پوء انهن مون کي تبصرن ۾ مدد ڪئي ۽ چيو ته انجيڪشن حڪمت عملي کي ترتيب ڏيڻ ممڪن آهي. ميپر انٽرفيس ۾ هڪ injectionStrategy فيلڊ آهي ، جيڪو صرف انجيڪشن اسٽريٽجي جو نالو قبول ڪري ٿو ، جنهن جا ٻه قدر آهن: FIELD ۽ CONSTRUCTOR . ھاڻي، اھو ڄاڻڻ، اچو ته ھن سيٽنگ کي اسان جي نقشن ۾ شامل ڪريو؛ مان اھو ڏيکاريندس LectureListMapper استعمال ڪندي مثال طور :
@Mapper(componentModel = "spring", uses = LectureMapper.class, injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public interface LectureListMapper {
   List<LectureModel> toModelList(List<LectureDTO> dtos);
   List<LectureDTO> toDTOList(List<LectureModel> models);
}
مون شامل ڪيل حصو کي ڳنڀير ۾ نمايان ڪيو. اچو ته هي آپشن ٻين سڀني لاءِ شامل ڪريون ۽ پروجيڪٽ کي ٻيهر ڪمپيل ڪريون ته جيئن ميپر نئين لائين سان ٺاهيا وڃن. هڪ دفعو اهو ٿي چڪو آهي، اچو ته ڏسو ته ڪيئن LectureListMapper لاءِ ميپر جو عمل تبديل ٿي چڪو آهي (جنهن کي اسان جي ضرورت آهي ان کي بولڊ ۾ نمايان ڪيو ويو آهي):
package com.github.romankh3.templaterepository.springboot.mapper;

import com.github.romankh3.templaterepository.springboot.dto.LectureDTO;
import com.github.romankh3.templaterepository.springboot.model.LectureModel;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Generated(
   value = "org.mapstruct.ap.MappingProcessor",
   date = "2021-12-09T22:25:37+0300",
   comments = "version: 1.4.2.Final, compiler: javac, environment: Java 15.0.2 (N/A)"
)
@Component
public class LectureListMapperImpl implements LectureListMapper {

   private final LectureMapper lectureMapper;

   @Autowired
   public LectureListMapperImpl(LectureMapper lectureMapper) {

       this.lectureMapper = lectureMapper;
   }

   @Override
   public List<LectureModel> toModelList(List<LectureDTO> dtos) {
       if ( dtos == null ) {
           return null;
       }

       List<LectureModel> list = new ArrayList<LectureModel>( dtos.size() );
       for ( LectureDTO lectureDTO : dtos ) {
           list.add( lectureMapper.toModel( lectureDTO ) );
       }

       return list;
   }

   @Override
   public List<LectureDTO> toDTOList(List<LectureModel> models) {
       if ( models == null ) {
           return null;
       }

       List<LectureDTO> list = new ArrayList<LectureDTO>( models.size() );
       for ( LectureModel lectureModel : models ) {
           list.add( lectureMapper.toDTO( lectureModel ) );
       }

       return list;
   }
}
۽ ھاڻي Mapstruct ٺاھيو آھي ميپر انجيڪشن ٺاھيندڙ ذريعي. اهو ئي آهي جيڪو اسان حاصل ڪرڻ جي ڪوشش ڪري رهيا هئاسين. هاڻي اسان جو امتحان گڏ ڪرڻ بند ٿي ويندو، اچو ته ان کي تازه ڪاري ڪريون ۽ حاصل ڪريو:
package com.github.romankh3.templaterepository.springboot.mapper;

import com.github.romankh3.templaterepository.springboot.dto.LectureDTO;
import com.github.romankh3.templaterepository.springboot.model.LectureModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.Collections;
import java.util.List;

class LectureListMapperTest {

   private final LectureListMapper lectureListMapper = new LectureListMapperImpl(new LectureMapperImpl());

   @Test
   void shouldProperlyMapListDtosToListModels() {
       //given
       LectureDTO dto = new LectureDTO();
       dto.setId(12L);
       dto.setName("I'm BATMAN!");

       List<LectureDTO> dtos = Collections.singletonList(dto);

       //when
       List<LectureModel> models = lectureListMapper.toModelList(dtos);

       //then
       Assertions.assertNotNull(models);
       Assertions.assertEquals(1, models.size());
       Assertions.assertEquals(dto.getId(), models.get(0).getId());
       Assertions.assertEquals(dto.getName(), models.get(0).getName());
   }
}
ھاڻي، جيڪڏھن اسان ٽيسٽ ھلائينداسين، سڀ ڪجھ ڪم ڪندو جيئن توقع ڪئي وئي، ڇو ته LectureListMapperImpl ۾ اسان LectureMapper پاس ڪريون ٿا ان جي ضرورت آھي... فتح! اهو توهان لاءِ مشڪل ناهي، پر مان خوش آهيان: دوستو، سڀ ڪجهه معمول مطابق آهي، سبسڪرائب ڪريو منهنجي GitHub اڪائونٽ تي ، منهنجي ٽيليگرام اڪائونٽ تي . اتي آئون پنھنجي سرگرمين جا نتيجا پوسٽ ڪريان ٿو، اتي واقعي مفيد شيون آھن) مان توھان کي خاص طور تي دعوت ڏيان ٿو توھان کي ٽيليگرام چينل جي بحث واري گروپ ۾ شامل ٿيڻ لاءِ . ائين ٿئي ٿو ته جيڪڏهن ڪنهن وٽ ٽيڪنيڪل سوال آهي، ته هو اتي ئي جواب حاصل ڪري سگهن ٿا. هي فارميٽ هر ڪنهن لاءِ دلچسپ آهي، توهان پڙهي سگهو ٿا ڪير ڄاڻي ٿو ۽ تجربو حاصل ڪري ٿو.

نتيجو

هن مضمون جي حصي جي طور تي، اسان Mapstruct جي طور تي اهڙي ضروري ۽ اڪثر استعمال ٿيل پراڊڪٽ سان واقف ٿي چڪا آهيون. اسان کي معلوم ٿيو ته اهو ڇا آهي، ڇو ۽ ڪيئن. هڪ حقيقي مثال استعمال ڪندي، اسان محسوس ڪيو ته ڇا ٿي سگهي ٿو ۽ اهو ڪيئن تبديل ٿي سگهي ٿو. اسان اهو پڻ ڏٺو ته ڪنسٽرڪٽر جي ذريعي ڀاڄين جي انجيڪشن کي ڪيئن ٺهرايو وڃي، انهي ڪري اهو ممڪن ٿيندو ته صحيح طريقي سان ميپرز کي جانچڻ. Mapstruct جي ساٿين انهن جي پراڊڪٽ جي استعمال ڪندڙن کي اجازت ڏني ته صحيح طور تي اهو چونڊيو ته ڪيئن ميپر کي انجڻ ڪجي، جنهن لاءِ اسان بلاشڪ انهن جا شڪرگذار آهيون. پر، ان حقيقت جي باوجود ته اسپرنگ ڪنسٽرڪٽر ذريعي ڀاڄين کي انجيڪشن لڳائڻ جي سفارش ڪري ٿو، Mapstruct جي ماڻهن ڊفالٽ طور فيلڊ ذريعي انجڻ مقرر ڪيو آهي. ائين ڇو آهي؟ ڪو جواب نه. مون کي شڪ آهي ته شايد اهڙا سبب آهن جن جي باري ۾ اسان کي خبر ناهي، ۽ اهو ئي سبب آهي ته انهن هن طريقي سان ڪيو. ۽ انھن مان معلوم ڪرڻ لاءِ، مون ٺاھيو GitHub مسئلو انھن جي سرڪاري پراڊڪٽ مخزن تي.
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION