인프런 커뮤니티 질문&답변

kim님의 프로필 이미지
kim

작성한 질문수

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

회원 기능 테스트

Test @Autowired질문 드립니다.

해결된 질문

작성

·

213

0

B라는 클래스에

@Autowired 로 C를 받고

C.start()라는 함수가 있을 때

BTest 클래스에서  C.start() 실행하면 C가 null포인트가 발생하는데 월래 Autowired로 받은 클래스는 Test에서 사용을 못하나요? Bean을 찾지를 못하는 것 같습니다.

답변 6

3

김영한님의 프로필 이미지
김영한
지식공유자

DTO 객체를 빈으로 등록해서 사용하는 것은 좋지 않습니다.

도메인 주도 설계 방식이라도 서비스단에서 주입을 해서 처리하는게 더 좋습니다.

DTO들은 가급적 순수하게 데이터만 들고 있는 것이 좋습니다.

꼭 필요하면 서비스에서 주입받은 PasswordEncoder 자체를 @Autowired가 아니라 PostAccount 사용 시점에 파라미터로 넘기는 것도 하나의 방법입니다.

이런식으로요.

public Account toAccount(PasswordEncoder encoder) {
...
}

감사합니다.

2

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. Kim님

스프링 빈으로 등록해야 @Autowired가 적용됩니다.

PostAccount는 스프링 빈이 아니기 때문에 @Autowired가 적용되지 않습니다.

감사합니다.

0

kim님의 프로필 이미지
kim
질문자

답변감사합니다~

0

kim님의 프로필 이미지
kim
질문자

답변감사합니다 

DTO객체를 빈으로 등록해서 사용하기도 하나요?

저렇게 postaccount에서 암호화하는게 도메인주도 설계방식이라 생각되어서 저렇게 만들어 본것이거든요. 책임을 DTO로 준건데 그냥 서비스단에서 주입을 해서 로직을 처리하는게 나을까요?

0

kim님의 프로필 이미지
kim
질문자

회원기능을 만들어 볼려고하는 중이였습니다~


@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Bean
public PasswordEncoder passwordEncoder(){
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

@Override
public void configure(WebSecurity web) {
web.ignoring().requestMatchers(PathRequest.toStaticResources().atCommonLocations());
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().permitAll();
}
}

이렇게 PasswordEncoder를 Bean으로 등록하였습니다.


@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Account extends BaseTimeEntity implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String username;

private String password;

private String email;

@Builder
public Account(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
}

회원 정보 테이블입니다.


public interface AccountRepository extends JpaRepository<Account, Long>{

}

Repository입니다.

@Getter
@Setter
public class PostAccount {

@Autowired
PasswordEncoder passwordEncoder;

@NotBlank(message = "이름은 필수 값입니다.")
private String username;

@NotBlank(message = "비밀번호는 필수 값입니다.")
private String password;

@NotBlank(message = "이메일은 필수 값입니다")
@Pattern(regexp = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\\\.[A-Za-z]{2,6}$", message = "이메일 형식이 아닙니다.")
private String email;


@Builder
public PostAccount(@NotBlank(message = "이름은 필수 값입니다.") String username,
@NotBlank(message = "비밀번호는 필수 값입니다.") String password,
@NotBlank(message = "이메일은 필수 값입니다") @Pattern(regexp = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\\\.[A-Za-z]{2,6}$", message = "이메일 형식이 아닙니다.") String email
) {
this.username = username;
this.password = password;
this.email = email;
}

public Account toAccount(){
return Account.builder()
.password(passwordEncoder.encode(password))
.username(username)
.email(email)
.build();
}
}

PostAccount는 Account의 DTO입니다. toAccount 함수에서 .password(passwordEncoder.encode(password)) 이 부분이 문제가 됩니다.



@RunWith(SpringRunner.class)
@SpringBootTest
public class AccountTest {
@Autowired
AccountRepository accountRepository;


@Test
public void PostAccount_객체로_받아와서_Account_Entity_로_변환하고_DB에_저장하기(){
PostAccount postAccount = PostAccount.builder()
.username("ym")
.password("1234")
.email("ym@email.com")
.build();
Account save = accountRepository.save(postAccount.toAccount());
assertEquals("username은 ym이다", "ym",save.getUsername());
assertEquals("password는 1234이다", "1234", save.getPassword());
assertEquals("email은 ym@email.com이다","ym@email.com", save.getEmail());
}

}
이것이 실행한 테스트이고

java.lang.NullPointerException

at com.ym.shop.domain.account.dto.PostAccount.toAccount(PostAccount.java:43)

at com.ym.shop.domain.account.entity.AccountTest.PostAccount_객체로_받아와서_Account_Entity__변환하고_DB_저장하기(AccountTest.java:29)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)

at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)

at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)

at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)

at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)

at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)

at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)

at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)

at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)

at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)

at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)

at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)

at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)

at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)

at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)

at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)

at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)

at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)

at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)

at org.junit.runners.ParentRunner.run(ParentRunner.java:363)

at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)

at org.junit.runner.JUnitCore.run(JUnitCore.java:137)

at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)

at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)

at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)

at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

null point에러가 발생합니다.
PostAccount에서
@Autowired
PasswordEncoder passwordEncoder;

이 부분이 테스트에서는 주입이 안되는 것 같습니다.

0

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. kim님

뭔가 설정이 잘못된 것 같습니다^^

클래스 C가 스프링 빈으로 등록이 안된 것 같아요.

github 같은곳에 동작하는 코드를 올려주시면, 도움을 드릴께요^^

kim님의 프로필 이미지
kim

작성한 질문수

질문하기