실용적인 대답을 찾고 있다면 여기 내 생각 중 하나입니다.
고객 계정을 가져 와서 API의 입력에 맞게 수정하려고한다고 가정 해 보겠습니다.
그래서 다음과 같이 보일 것입니다 데이터 층 또는 쿼리를 작성 :
type CustomerAccount struct{
id string // this data type will differ depends on your database.
Name string
Address string
Age int
// and any other attribute. this is just for example.
}
func (ca *CustomerAccount)GetCustomerAccount (id int) (CustomerAccount,error) {
var ca CostumerAccount
// write your query using any databases.
// return an error if error happens when you do query to the database.
return ca,nil
}
func (ca *CustomerAccount)SaveCustomerAccount(ca CustomerAccount) error {
// find and update the data from given CustomerAccount
return nil
}
저장 코드를 customer_account.go
명명 위.
이제 비즈니스 로직 또는이 경우 BLL을 사용하는 DAL에서 데이터베이스 쿼리를 분리하려고한다고 가정 해 보겠습니다. 당신은 그 인터페이스를 사용할 수 있습니다. customer_account_interface.go
로 저장
type CustomerAccountInterface interface {
GetCustomerAccount (id int) (CustomerAccount,error)
SaveCustomerAccount(ca CustomerAccount) error
}
: 인터페이스이 같은 위의 모델 쿼리 방법을 마녀 일치 유형을 만들기.
이제 우리는 데이터 수정에 대한 책임이있는 비즈니스 로직을 작성하고자하며, CusomerAccountInterface
을 비즈니스 로직으로 호출 할 것입니다. 데이터 액세스 또는 우리가 단위를 만들 수 있도록 쿼리 데이터베이스와 비즈니스 로직 우리가 핸들러를 분리 한 위의 접근 방식에서
func EditCustomerAccount(ca CustomerAccountInterface) http.Handler {
return http.HandleFunc(func(w http.ResponseWritter, r *http.Request){
// get all the input from user using *http.Request like id and other input.
// get our CustomerAccount Data to modify it
customerAccount,err := ca.GetAccountCustomer(id)
// modify customerAccount Accordingly from the input data, for example
customerAccount.Name = inputName // you can change what ever you want with the data here. In this case we change the name only for example purpose.
// save your customerAccount to your database
err := ca.SaveCustomerAccount(customerAccount)
// send the response 200 ok resonse if no error happens
w.WriteHeader(http.StatusOk)
resp := response{} // you can create your response struct in other places.
resp.Message = "success update data"
json.NewEncoder(w).Encode(resp)
})
}
: 우리가 혹 있도록 API를 만드는 때문에 우리는이에 대한 핸들러를 사용
type CustomerAccountMock struct {
err error
Data CutstomerAccount
}
func (ca *CustomerAccountMock)GetCustomerAccount (id int) (CustomerAccount,error) {
return ca.Data,nil
}
func (ca *CustomerAccountMock)SaveCustomerAccount(ca CustomerAccount) error {
return ca.err
}
이제 우리는이 같은 테스트 뭔가를 쓸 수 있습니다 :
데이터 액세스의 결과 쿼리를 조롱하는
이 CustomerAccountMock
만들기 :이 같은 핸들러 뭔가 비즈니스 로직에 대한 시험
func TestEditCustomerAccount(t *testing.T){
testObjects := []struct{
CMock CutomerAccountMock
}{
{
CMock : CustomerAccountMock{
err : errors.New("Test error")
Data : CustomerAccount{} // return an empty data
},
},
}
for _, testObject := range testObjects {
actualResponse := createRequestToHandler(testObject.CMock)
// here you can check your response from calling your request testing to your handler.
}
}
위의 아이디어를 얻는 것 이상으로 데이터 계층과 비즈니스 로직 계층을 분리하여 어떻게 접근해야합니까? 내 완전 source code here을 참조 할 수 있습니다. 이 코드는 드라이버 데이터를 업데이트하는 것과 같은 또 다른 테스트 케이스를 나타내지 만 동일한 접근법입니다.
하지만이 접근법에는 몇 가지 단점이 있습니다. 테스트에서는 수천 건의 기사 작성과 비슷합니다. 인내심을 가져야합니다.
그래서 귀하의 질문에
오는 그것은 이동 Web App에서 DAL 및 BLL이 필요하다?
예. 데이터 액세스를 비즈니스 로직 레이어와 분리하면 단위 테스트가 가능해집니다.
위의 예제에서 로직은 매우 간단하지만 데이터를 조작하는 복잡한 로직이 있고 DAL과 BLL을 분리하지 않는다고 상상해보십시오. 로직이나 쿼리를 변경하면 미래의 개발자와 다른 개발자에게 해를 입힐 것입니다.
뭔가 잘못되었을 때 변경하고 좌절감을 느끼는 것은 분명히 직업 생활에서 일어나는 것을 피하기를 원합니다.
이 정보가 도움이되는지 확인하십시오. http://stackoverflow.com/q/42791536/5779732, http://stackoverflow.com/a/42500771/5779732, http://stackoverflow.com/a/4/424700/5779732 –