inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

173만명의 커뮤니티!! 함께 토론해봐요.

@SQLRestriction으로 논리적 삭제 필드에 대한 tearDown에 대해 궁금합니다.

해결됨

Practical Testing: 실용적인 테스트 가이드

안녕하세요. 강의를 들은 후 테스트 코드 작성을 연습하고 있습니다. 엔티티에서 Soft delete를 위한 필드(isDeleted)가 정의되어 있습니다. Soft delete가 된 데이터는 조회할 필요가 없기 때문에 엔티티에 @SQLRestriction("is_deleted = false") 를 정의했습니다. 테스트 코드에서 해당 어노테이션 때문에 tearDown() 메서드 동작시 문제가 발생했습니다. .deleteAllInBatch() 가 실행될 때, where 조건이 포함되기 때문에 데이터가 삭제되지 않습니다. 상품 목록 조회에 대한 테스트 코드를 작성할 때, soft delete 된 데이터는 빠지고 정상적인 데이터만 조회되는지 보려고 isDeleted = true 값을 준 테스트 데이터도 생성해서 테스트 코드를 작성했습니다. 해당 경우에는 어떤식으로 테스트 코드를 작성해야 할까요? isDeleted = true 테스트 데이터를 만들지 않는다. @SQLRestriction("is_deleted = false") 를 사용하지 않고, 쿼리 조회 시 IsDeletedTrue 조건을 주도록 한다. 위 방법이 아닌 Best Practice가 있는지 궁금합니다. 아래는 테스트 코드 예시 입니다. @SQLRestriction("is_deleted = false") 적용된 엔티티 예시입니다. @Entity @SQLRestriction("is_deleted = false") @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Product extends BaseDateTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "product_id") private Long id; @Column(length = 50) private String name; private Boolean isDeleted; @OneToMany(mappedBy = "product", cascade = CascadeType.ALL) private List<ProductOption> productOptions = new ArrayList<>(); // ... 중략 } @Entity @SQLRestriction("is_deleted = false") @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class ProductOption extends BaseDateTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "product_option_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "product_id") private Product product; @Column(length = 30) private String name; private Boolean isDeleted; // ... 중략 } isDeleted = true 테스트 데이터를 포함한 테스트 코드 예시입니다. class ProductServiceTest extends ServiceTestSupport { @Autowired private ProductRepository productRepository; @AfterEach void tearDown() { productOptionRepository.deleteAllInBatch(); productRepository.deleteAllInBatch(); } @Test @DisplayName("상품 목록을 조회한다.") void getSellingProducts() throws Exception { // given ProductOption productOption1 = createProductOption("옵션1", false); ProductOption productOption2 = createProductOption("옵션2", false); ProductOption productOption3 = createProductOption("옵션3", false); ProductOption productOption4 = createProductOption("옵션4", true); // isDeleted = true ProductOption productOption5 = createProductOption("옵션5", false); ProductOption productOption6 = createProductOption("옵션6", true); // isDeleted = true Product product1 = createProduct("상품1", false, List.of(productOption1, productOption2)); Product product2 = createProduct("상품2", false, List.of(productOption3, productOption4)); Product product3 = createProduct("상품3", true, List.of(productOption5, productOption6)); // isDeleted = true productRepository.saveAll(List.of(product1, product2, product3)); // ... 중략 // when List<product> products = productService.getSellingProducts(); // then // ... 중략 } // ... 중략 } deleteAllInBatch() 메서드가 실행된 후 로그 입니다. Hibernate: delete from product_option where ( product_option.is_deleted = false ) Hibernate: delete from product where ( product.is_deleted = false ) org.springframework.dao.DataIntegrityViolationException: JDBC exception executing SQL [delete from product where (product.is_deleted = false)] [Referential integrity constraint violation: "FKN4HMM6EX1VGN60C6UIQTE400F: PUBLIC.PRODUCT_OPTION FOREIGN KEY(PRODUCT_ID) REFERENCES PUBLIC.PRODUCT(PRODUCT_ID) (CAST(3 AS BIGINT))"; SQL statement: delete from product where (product.is_deleted = false) [23503-224]] [n/a]; SQL [n/a]; constraint ["FKN4HMM6EX1VGN60C6UIQTE400F: PUBLIC.PRODUCT_OPTION FOREIGN KEY(PRODUCT_ID) REFERENCES PUBLIC.PRODUCT(PRODUCT_ID) (CAST(3 AS BIGINT))"; SQL statement: delete from product where (product.is_deleted = false) [23503-224]] 감사합니다.

  • spring
  • tdd
  • jpa
  • mockito
  • 소프트웨어-테스트
  • junit5
Anonymous 댓글 2 좋아요 0 조회수 1833

Util성 클래스와의 비교

미해결

Java/Spring 테스트를 추가하고 싶은 개발자들의 오답노트

안녕하세요 좋은 강의 만들어 주셔서 감사합니다. 많은 분들이 비슷한 질문을 해주신 것으로 생각되는데, Util성 클래스와 Holder인터페이스를 구현한 구체클래스의 의존주입의 사용 기준에 대해 여쭤보려고 합니다. 강의에서 예로 들어주신 SystemClockHolder의 경우 많은 예제에서 Util클래스로 만들어 사용할 것이라고 생각됩니다. 하지만 이렇게 되면 강의에서 말씀해주신 것처럼 메소드 내부에 사용자가 예측할 수 없는 값이 들어가게 되어 테스트하기 어려워지는 신호가 될 수 있다고 생각합니다. 반면 이러한 Holder가 너무 많아질 경우 서비스 계층에서 의존주입 받아야할 Holder가 너무 많아지지는 않을까 하는 고민도 되었습니다. 강사님께서는 어떤 기준으로 Util클래스와 인터페이스 기반의 의존주입 클래스를 구분하시는지 궁금합니다.

  • spring
  • tdd
  • jpa
  • 소프트웨어-테스트
  • unittest
skehdxhd 댓글 1 좋아요 0 조회수 301

강사님은 테스트를 어떻게 하시는지 궁금합니다.

해결됨

Practical Testing: 실용적인 테스트 가이드

학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요! 먼저 유사한 질문이 있었는지 검색해 보세요. 서로 예의를 지키며 존중하는 문화를 만들어가요. Classicist에 대해서 궁금해서 질문드립니다. 현업 또는 강사님 혼자서 컨트롤러만 테스트 할 경우 서비스 레이어를 mock, stub을 사용하시는지, 아니면 Fake Service 및 Fake Repository를 구현 후 컨트롤러 테스트를 하시는지 궁금합니다. Classicist을 추구하면 외부 환경만 Mock을 사용해서 테스트를 해야하는 지 아니면 최대한 Mock을 지양하지만 컨트롤러 테스트 같은 경우에는 Mock을 사용하나요?

  • spring
  • tdd
  • jpa
  • mockito
  • 소프트웨어-테스트
  • junit5
bha4388 댓글 1 좋아요 0 조회수 488

OrderProduct 테스트에 대해

미해결

Practical Testing: 실용적인 테스트 가이드

안녕하세요 강사님 먼저 강의에 대해 너무 감사드린다는 말씀 드리고 싶습니다. 강의 내용 중 OrderProduct를 생성하는 부분의 책임이 Order에 있게 설계하는 부분에 정말 매력을 느끼고, 유사한 설계 방법들에 대해 공부하려면 어떤 키워드를 알아보면 좋을까요?? 또한 이 강의를 따라 공부해서 개인적으로 진행중인 프로젝트에 적용하면서 공부하고 있는데, 딱 Order와 OrderProduct같은 관계에서 OrderProduct를 강의에서처럼 생성자가 아닌 정적 팩토리 메소드를 통해 만들어보고자 하였습니다. 하지만 여기에서 OrderProdcut의 정적 팩토리 메소드를 테스트하려면 Order가 필요하고, Order를 create하려면 또 OrderProduct가 내부에서 만들어지는 문제가 발생했습니다. 이런 경우는 어떻게 해결할 수 있을까요?? 임의로 Order에 대해 mock으로 생성해서 해결하고는 있는데, 이게 일반적인 방법이 될 수 있을까요? 감사합니다!!

  • spring
  • tdd
  • jpa
  • mockito
  • 소프트웨어-테스트
  • junit5
mmmmim 댓글 2 좋아요 1 조회수 385

SpringSecurity 사용 시 Controller 테스트

미해결

Practical Testing: 실용적인 테스트 가이드

안녕하세요 좋은 강의를 제공해주셔서 너무 감사합니다. 평소 테스트에 대해 고민하던 많은 부분이 해결되었습다. 그러나 아직 해결하지 못 한 부분이 있습니다. 전 개인 프로젝트에 Spring Security 를 이용해 인증 및 인가를 구현하였습니다. 또한, 컨트롤러에 @AuthenticationPrincipal 을 이용해 인증 객체를 가져와 로그인한 회원의 정보를 사용하고 있습니다. 강사님의 경우 @WebMvcTest 를 이용해 컨트롤러만 띄워 최소한의 파라미터만 검증하였습니다. 저 역시 처음엔 @WebMvcTest 를 이용해 최소한의 비용으로 컨트롤러를 테스트해보려 했으나 테스트 수행 시 Security 관련 빈이 없어 잦은 오류가 발생하였습니다. 이 경우 @WebMvcTest 를 그대로 사용하며 TestSupport 와 같은 클래스에 시큐리티 관련 빈들을 모두 목킹하고 @AuthenticationPrincipal 으로 가져오는 인증객체 또한 목킹하는 것이 좋은 테스트일지 @SpringBootTest 를 사용한 다음 인증객체를 주입하는 것이 좋은 테스트인지 잘 판단이 안됩니다. (@AuthenticationPrincipal 의 경우 컨트롤러 메서드의 파라미터로 들어가는데 이것 역시 목킹이 가능한지도 잘 감이 안잡힙니다.) 마지막으로 Spring Security 를 구성하는 필터 혹은 인터셉터나 kafka, websocket 같은 비동기 통신의 경우 실무에서 어떻게 테스트를 수행하는지 궁금합니다! 긴 질문 읽어주셔서 감사합니다

  • spring
  • tdd
  • jpa
  • mockito
  • 소프트웨어-테스트
  • junit5
asdf 댓글 2 좋아요 1 조회수 881

인수 테스트에 대한 비중은 어느정도로 가져가는게 좋다고 생각하시나요?

해결됨

Practical Testing: 실용적인 테스트 가이드

안녕하세요 강사님.! 좋은 강의 잘 들었습니다.! 덕분에 좋은 자산을 남겨 놓을 수 있을 거 같습니다. 이번 강의에서 인수 테스트에 관한 내용은 없어서 인수 테스트에 관한 강사님의 전반적인 견해가 궁금합니다. 1) 다른 단위/통합 테스트에 비해서 인수 테스트에 대한 중요도가 낮다고 생각하시나요? 2) 현업에서 인수 테스트에 대한 비중은 어느 정도로 가지고 가시나요? 개인적으로는 가장 사용자 친화적인(?) 인수테스트도 중요하다고 생각하고 있습니다. 감사합니다.! 좋은 하루 되세요!

  • spring
  • tdd
  • jpa
  • mockito
  • 소프트웨어-테스트
  • junit5
  • 인수테스트
  • restassured
윤경준 댓글 2 좋아요 0 조회수 539

create test 부분에서 시퀀스 문제가 있습니다.

미해결

Java/Spring 테스트를 추가하고 싶은 개발자들의 오답노트

단일 테스트는 문제 없지만 전체 테스트 진행 시 테이블의 id의 시퀀스가 계속 증가 하는 문제로 jpa save 시 id 1에 저장하려는 문제가 발생하여 user-service-test-data.sql -- insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) -- values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); -- insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) -- values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); insert into `users` (`email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) values ('kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); insert into `users` (`email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) values ('kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); post-service-test-data.sql -- insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) -- values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); -- insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) -- values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); -- insert into `posts` (`id`, `content`, `created_at`, `modified_at`, `user_id`) -- values (1, 'helloworld', 1678530673958, 0, 1); insert into `users` (`email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) values ('kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); insert into `users` (`email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) values ('kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); insert into `posts` (`content`, `created_at`, `modified_at`, `user_id`) values ('helloworld', 1678530673958, 0, 1); delte-all-data.sql delete from `posts` where 1; delete from `users` where 1; ALTER TABLE `users` ALTER COLUMN id RESTART WITH 1; ALTER TABLE `posts` ALTER COLUMN id RESTART WITH 1; 이와 같이 변경하였는데 혹시 다른 방법이 있을까요?

  • spring
  • tdd
  • jpa
  • 소프트웨어-테스트
  • unittest
박기현 댓글 3 좋아요 1 조회수 899

테스트 코드에서 @BeforeEach가 아니라 sql 사용하시는 이유 문의드립니다.

미해결

Java/Spring 테스트를 추가하고 싶은 개발자들의 오답노트

안녕하세요! 실무에서 테스트 코드 적용을 위해 강의를 열심히 듣고 있는 중 궁금한 부분이 있습니다. 테스트코드 사용 시 @BeforeEach를 사용하는 경우도 있는데, sql로 초기 데이터 추가를 사용하시는 이유가 궁금합니다. 작은 서비스가 아니고 복잡한 서비스의 경우 sql로 넣는게 편할것 같기는 한데, 상태에 따라 id값이 필요한 경우도 있고, sql로 작성 시 테스트 마다 데이터가 적용이 동일하지 않을 것 같기도 해서 실제 복잡한 프로젝트에서 어떻게 사용하시는지 궁금해서 문의드립니다. @BeforeEach가 한눈에 들어오지 않아서 잘 사용하지 않으신다고 설명해 주시기는 했지만, SQL로 사용 시 조회 등의 테스트에서는 특정 상태의 데이터 id를 알아야 하고, 그럼 SQL에서 해당 데이터의 id값과 상태값을 다시 확인해야 하는 형태는 동일하게 한눈에 안 들어올 것 같아서 고민이 되더라고요. 저도 SQL로 초기 데이터를 추가하는 형태로 사용하다가 이후에 테스트 코드의 유지보수가 쉽지 않은 경험이 있어서 강사님께서는 복잡한 비즈니스의 실무에서는 어떻게 사용하시는 궁금합니다. 감사합니다.

  • spring
  • tdd
  • jpa
  • 소프트웨어-테스트
  • unittest
wony 댓글 1 좋아요 0 조회수 703

TypeError: user_model_1.default.create is not a function

미해결

따라하며 배우는 TDD 개발 [2023.11 업데이트]

학습중 repository pattern을 적용하여 테스트를 적용해 보던 중 TypeError: user_model_1.default.create is not a function 라는 에러와 마주하게 되었습니다. user.repository.ts import User from "../model/user.model"; export class UserRepository { createUser = async(user) => { const newUser = await User.create({ ...user }) return newUser } findUserById = async(id:string) => { const user = await User.findById('65cba34813b2fbec74a558a8') if(!user) throw new Error('존재하지 않는 유저정보 입니다.') return user } } user.repository.test.ts import { UserRepository } from "../../app/repository/user.repository" const createMock = jest.fn() const findByIdMock = jest.fn() jest.mock("../../app/model/user.model", () => { return { User: jest.fn(() => { return { create:createMock, findById:findByIdMock } }) } }) describe('user repository Create', () => { let sut:UserRepository; const newUser = { id:"abcdefrwgsf123123", name:"test name", email:"test@nanana.com" } beforeEach(() => { sut = new UserRepository() }) afterEach(() => { jest.clearAllMocks() }) it('create api', async () => { createMock.mockReturnValueOnce(newUser) const actual = await sut.createUser({name:newUser.name, email:newUser.email}) expect(createMock).toHaveBeenCalledTimes(1) expect(actual).toStrictEqual(newUser) expect(createMock).toHaveBeenCalledWith({name:newUser.name, email:newUser.email}) }) }) jest실행시 create api의 createMock.mockReturnValue() 까지는 실행이되지만 await sut.createUser() 부분에서 에러가 나는것으로 확인되었습니다.

  • node.js
  • mongodb
  • express
  • supertest
  • tdd
  • jest
  • mongoose
  • 소프트웨어-테스트
양진영 댓글 1 좋아요 0 조회수 284

@RequestParam vs @ModelAttribute

해결됨

Practical Testing: 실용적인 테스트 가이드

강의에 나온 내용은 아니지만 개인적으로 개발을하다 궁금한 점이 생겨서 질문 드립니다. 조회 API를 만들 때 (GET요청)Controller단에서 파라미터를 받는 방식이 @RequestParam, @ModelAttribute 크게 2가지 있는데 2가지 방식중 어떤 방식을 선호하지는지 질문드립니다. @RequestParm을 사용했을 때는 Controller단에서 바로 직관적으로 어떤 파라미터를 받는지 확인이 가능하다는 장점이 있지만 Service단으로 파라미터를 넘겨줄 때, 하나하나 넘겨줘야해서 파라미터가 추가되었을 때 불편하다는 점이 있을 테고 @ModelAttribute를 사용했을 때는 수정에는 유리하겠지만 가독성은 떨어질 것 같다는 생각이 듭니다. 강사님은 어떤 생각을 가지고 계신지, 현업에서는 주로 어떤방식으로 개발을 하는지 의견주시면 감사하겠습니다.

  • spring
  • tdd
  • jpa
  • mockito
  • 소프트웨어-테스트
  • junit5
psam1017 댓글 2 좋아요 0 조회수 532

오류메세지는 확인했는데 어떻게 고쳐야 할지 모르겠습니다 ㅠ

미해결

따라하며 배우는 리액트 A-Z[19버전 반영]

TODO앱을 클래스앱에서 컴포넌트 함수형 으로 바꾸는과정에서 뭔가 문제가 생겼는지 아니면 이전부터 문제가 있었는지는 모르겠는데 이런오류가 뜨면서 되지않네요 ㅠㅠ 리액트 초짜라 뭘 어떻게 바꿔야할지 모르겠습니다 ㅠㅠ 답변부탁드립니다 감사합니다 ㅠㅠ 위에 문제가 된다고 하는 6행 74행 사진입니다 ㅠㅠ

  • react
  • redux
  • tdd
  • typescript
  • 소프트웨어-테스트
나래 댓글 1 좋아요 0 조회수 317

사용되는 아키텍처에 대해

미해결

Practical Testing: 실용적인 테스트 가이드

학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요! 먼저 유사한 질문이 있었는지 검색해 보세요. 서로 예의를 지키며 존중하는 문화를 만들어가요. 안녕하세요 선생님 강의 잘보고 있습니다. 질문드리고 싶은 부분은 강의에서 사용되는 아키텍처에 대한 것입니다. 레이어드 아키텍처라는것은 이해했지만, 패키지 구조가 생소해서 어떻게 구성되는지는 이해하기 어려운것 같습니다. 제가 아는 방식은 컨트롤러, 서비스, 리파짓토리, 도메인 패키지로 단순하게 작성하는 방법인데, 여기서 사용된 패키지 구성방식과 관련된 키워드나 레퍼런스를 얻을 수 있을가요?

  • spring
  • tdd
  • jpa
  • mockito
  • 소프트웨어-테스트
  • junit5
gukin.dev 댓글 2 좋아요 0 조회수 581

에러 처리를 위한 단위테스트 작성

미해결

따라하며 배우는 TDD 개발 [2023.11 업데이트]

에러 처리를 위한 단위테스트 작성 강의 내용 중 이해가 가지 않는 부분이 생겨 글 남김니다. errorMessage 의 message 내용은 description property missing 에러입니다. 그렇다면 테스트 상황에서 포스트맨과 동일하게 description이 빠진 객체를 저장하다 에러가 발생해야 맞는 테스트가 아닌가 하는 의문이 생기네요. it('should handle errors', async () => { const errorMessage = {message: "description property missing"}; const rejectedPromise = Promise.reject(errorMessage); productModel.create.mockReturnValue(rejectedPromise); await controller.createProduct(req, res, next); expect(next).toBeCalledWith(errorMessage); })

  • node.js
  • mongodb
  • express
  • supertest
  • tdd
  • jest
  • mongoose
  • 소프트웨어-테스트
ce ce 댓글 1 좋아요 0 조회수 380

안녕하세요 재고 테이블에 대해서 질문 있습니다.!

해결됨

Practical Testing: 실용적인 테스트 가이드

안녕하세요 멘토님 강의 잘듣고 있습니다! 제가 테이블을 언제 만들어야 하고 합쳐야 되는지에 대해서 잘 모르겠습니다. 혹시 검색 키워드와 상품테이블에서 재고를 관리하지 않고 따로 테이블을 만든 이유가 있을까요 ?

  • spring
  • tdd
  • jpa
  • mockito
  • 소프트웨어-테스트
  • junit5
qheogus55 댓글 2 좋아요 2 조회수 742

creactStore질문이요

미해결

따라하며 배우는 리액트 A-Z[19버전 반영]

미들웨어에서 rootReducer 하나만 넣었을 땐 문제 없는데 2번째 인자 넣을때부터 에러가 계속 나는데 이유를 모르겠습니다.

  • react
  • redux
  • tdd
  • typescript
  • next.js
  • 소프트웨어-테스트
악보-Designer Park 댓글 2 좋아요 1 조회수 316

맥북 프로 14 가상화 확인

미해결

Do It! 장고+부트스트랩: 파이썬 웹개발의 정석

안녕하세요 강사님 저는 지금 현재 도커 소개와 도커 설치 강의를 수강하고 있습니다. window에서는 작업 관리자에 들어가면 가상화를 확인할 수 있지만 제가 사용하고 있는 맥북 프로 14에서는 가상화가 사용되고 있는지 확인 할 수 없습니다. 그래서 구글에도 검색을 해 보았는데 무슨 말인지 정확히 이해하기 힘들어 질문을 남깁니다. 맥북 프로 14 모델에서는 가상화가 사용되고 있는것인가요? 만약 사용되고 있지 않다면 무엇을 어떻게 설치해야 하는지 알려주시면 감사하겠습니다.

  • HTML/CSS
  • javascript
  • python
  • django
  • bootstrap
  • aws
  • docker
  • tdd
최기연 댓글 2 좋아요 0 조회수 453

혹시 git 플러그인 아시는 분

미해결

Java/Spring 테스트를 추가하고 싶은 개발자들의 오답노트

수업에서 git 커밋메세지 사용할 때 옆에 나오는 것들 어떻게 나오는지 아시는 분 계시나요? intellij 기능인지 플러그인인지 인 것 같은데요. 아시는 분 있으시면 답변 주시면 감사하겠습니다.

  • spring
  • tdd
  • jpa
  • 소프트웨어-테스트
  • unittest
런런 댓글 1 좋아요 0 조회수 537

이상한 url로 요청해도 200이 반환됩니다. 그리고 body가 비어있어요...

미해결

Practical Testing: 실용적인 테스트 가이드

@WebMvcTest(CompanyController::class) @ActiveProfiles("test") @WithMockUser class CompanyControllerTest { @Autowired lateinit var mockMvc: MockMvc @MockBean lateinit var getCompanyService: GetCompanyService @MockBean lateinit var adminAuthorizationFilter: AdminAuthorizationFilter private val cookie = Cookie(ADMIN_AUTH_TOKEN, "admin-auth-token") @DisplayName("회사 목록 조회") @Test fun findAll() { // given val companies = listOf( companyEntity(1, "A"), companyEntity(2, "B"), companyEntity(3, "C"), ) `when`(getCompanyService.findAll()).thenReturn(companies) // when val request = MockMvcRequestBuilders.get("/admin/api/v1/companies") .cookie(cookie).accept(MediaType.APPLICATION_JSON) // then mockMvc.perform(request) .andExpect(MockMvcResultMatchers.status().isOk) .andDo(MockMvcResultHandlers.print()) } } 위 코드를 가지고 질문드리겠습니다. val request = MockMvcRequestBuilders.get("/admin/api/v1/companies") 이 부분에서 companies가 아니라 존재하지 않는 url(ex. /admin/api/v1/cfasfsdfcompanies )라고 한 후 위 코드를 돌리면 200나옵니다. 존재하지 않는 url도 호출이 가능한건가요? 그리고 body가 항상 빈 값입니다. MockHttpServletResponse: Status = 200 Error message = null Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", X-Content-Type-Options:"nosniff", X-XSS-Protection:"0", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"] Content type = null Body = Forwarded URL = null Redirected URL = null Cookies = [] 목킹이 잘못되었는지 점검해보려고 getCompanyService.findAll() 를 호출해보았는데 3개가 정상적으로 나옵니다. 혹시 몰라 소스 공유드립니다. // controller @RestController @RequestMapping("/admin/api/v1/companies") class CompanyController( private val getCompanyService: GetCompanyService ) { @GetMapping fun findAll(): List<CompanyResponse> { return getCompanyService.findAll().map { CompanyResponse.of(it) } } } // service @Service @Transactional(readOnly = true) class GetCompanyService( private val companyFindService: CompanyFindService ) { fun findAll(): List<CompanyEntity> { return companyFindService.findAll() } }

  • spring
  • tdd
  • jpa
  • mockito
  • 소프트웨어-테스트
  • junit5
Louie(루이) 댓글 2 좋아요 0 조회수 914

RestDocs에서의 SpringSecurity Issue

미해결

Practical Testing: 실용적인 테스트 가이드

public class FollowControllerDocsTest extends RestDocsSupport { private FollowService followService = mock(FollowService.class); @Override protected Object initController() { return new FollowController(followService); } private final Long loginUserId = 1L; @DisplayName("팔로우 수행 API") @WithUserDetails @Test public void startFollow() throws Exception { // Given StartFollowRequestDto requestDto = StartFollowRequestDto.builder() .followerId(loginUserId) .followingId(123L) .build(); BDDMockito.doReturn(StartFollowResponseDto.success()) .when(followService) .follow(any(StartFollowRequestDto.class)); //when,then mockMvc.perform( post("/api/follow/start-follow") .with(csrf()) .content(objectMapper.writeValueAsString(requestDto)) .contentType(MediaType.APPLICATION_JSON) ) .andExpect(status().isOk()) .andDo(document("start-follow", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), requestFields( fieldWithPath("followerId").type(JsonFieldType.STRING) .optional() .description("팔로워 아이디"), fieldWithPath("followingId").type(JsonFieldType.STRING) .optional() .description("팔로잉 아이디") ), responseFields( fieldWithPath("code").type(JsonFieldType.STRING) .description(ResponseCode.SUCCESS), fieldWithPath("message").type(JsonFieldType.STRING) .description(SUCCESS) ) )); } } FollowController @RestController @RequestMapping("/api/follow") @RequiredArgsConstructor public class FollowController { private final FollowService followService; @PostMapping("/start-follow") ResponseEntity<? super StartFollowResponseDto> startFollow( @RequestBody @Valid StartFollowRequestDto requestBody, @AuthenticationPrincipal PrincipalDetails principalDetails ) { Long loginId = principalDetails.getUser().getId(); Long userId = requestBody.getFollowerId(); if (loginId != userId) return StartFollowResponseDto.certificationFail(); ResponseEntity<? super StartFollowResponseDto> response = followService.follow(requestBody); return response; } } RestDocsSupport @ExtendWith(RestDocumentationExtension.class) public abstract class RestDocsSupport { protected MockMvc mockMvc; protected ObjectMapper objectMapper = new ObjectMapper(); private final Long loginUserId = 1L; @BeforeEach void setUp(RestDocumentationContextProvider provider) { User user = mock(User.class); when(user.getId()).thenReturn(loginUserId); PrincipalDetails userDetails = mock(PrincipalDetails.class); when(userDetails.getUser()).thenReturn(user); SecurityContext context = SecurityContextHolder.getContext(); context.setAuthentication(new UsernamePasswordAuthenticationToken(userDetails, null, null)); this.mockMvc = MockMvcBuilders .standaloneSetup(initController()) .apply(MockMvcRestDocumentation.documentationConfiguration(provider)) .build(); System.out.println("beforeEach 수행"); } protected abstract Object initController(); } 안녕하세요. 강의 정말 유익하게 잘 듣고있습니다. 강의를 듣고 restdocs를 작성하던 중 문제가 발생하여 질문을 올립니다. 제가 작성한 controller에서는 파라미터로 security.context 안에 있는 PrincipalDetails를 받아옵니다. 그렇지만 테스트에선 그 안에 값이 있는게 아니여서 Mock값을 넣어주어 @WebMvcTest 에서는 문제를 해결해 왔었습니다. 문제는 restdocs를 작성하기 위한 테스트 코드에서 발생하였습니다. 이 테스트 코드에는 제가 적용한 PrincipalDetails 몫 이 넣어지지 않는 문제가 있었습니다. 제가 생각하기론 SpringSecurity가 올라가지 않아서 그런 것 같은데 해결방법이 있으면 알고싶습니다 !

  • spring
  • tdd
  • jpa
  • mockito
  • 소프트웨어-테스트
  • junit5
김승수 댓글 2 좋아요 -1 조회수 594

인기 태그

인프런 TOP Writers

주간 인기글