test: 后端自动化测试套件

Service 单元测试(SQLite in-memory):
- auth: 登录成功/失败/禁用账号,token 刷新
- stock: 入库审核、出库审核(含库存不足)、单号生成
- license: 激活、设备绑定验证、过期检测

Handler 集成测试(httptest + SQLite):
- auth: 登录 API 成功/401 场景
- product: CRUD 完整流程 + hotel_id 隔离验证
- stock_in: 创建→提交→审核完整流程
- stock_out: 完整流程 + 库存不足 400
- inventory: 库存查询/过滤/盘点创建
- warehouse: CRUD

覆盖率:service 90.4%,handler 56.1%
共 50 个测试用例,全部 PASS

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-04-04 07:24:14 +08:00
parent 0e42f0e417
commit 7a09d1537c
13 changed files with 2292 additions and 0 deletions
+132
View File
@@ -0,0 +1,132 @@
package service
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/wangjia/jiu/backend/testutil"
)
func TestAuthService_Login_Success(t *testing.T) {
db := testutil.SetupTestDB()
hotel := testutil.CreateTestHotel(db, "HOTEL001")
testutil.CreateTestUser(db, hotel.ID, "admin", "password123", "admin")
svc := NewAuthService(db)
pair, user, err := svc.Login("HOTEL001", "admin", "password123")
require.NoError(t, err)
require.NotNil(t, pair)
require.NotNil(t, user)
assert.NotEmpty(t, pair.AccessToken)
assert.NotEmpty(t, pair.RefreshToken)
assert.Equal(t, "admin", user.Username)
}
func TestAuthService_Login_WrongPassword(t *testing.T) {
db := testutil.SetupTestDB()
hotel := testutil.CreateTestHotel(db, "HOTEL002")
testutil.CreateTestUser(db, hotel.ID, "admin", "password123", "admin")
svc := NewAuthService(db)
pair, user, err := svc.Login("HOTEL002", "admin", "wrongpassword")
assert.Error(t, err)
assert.Equal(t, ErrInvalidCredentials, err)
assert.Nil(t, pair)
assert.Nil(t, user)
}
func TestAuthService_Login_WrongHotel(t *testing.T) {
db := testutil.SetupTestDB()
testutil.CreateTestHotel(db, "HOTEL003")
svc := NewAuthService(db)
pair, user, err := svc.Login("NONEXISTENT", "admin", "password123")
assert.Error(t, err)
assert.Equal(t, ErrInvalidCredentials, err)
assert.Nil(t, pair)
assert.Nil(t, user)
}
func TestAuthService_Login_DisabledUser(t *testing.T) {
db := testutil.SetupTestDB()
hotel := testutil.CreateTestHotel(db, "HOTEL004")
user := testutil.CreateTestUser(db, hotel.ID, "disabled", "password123", "operator")
// 禁用用户
db.Model(user).Update("is_active", false)
svc := NewAuthService(db)
pair, u, err := svc.Login("HOTEL004", "disabled", "password123")
assert.Error(t, err)
assert.Equal(t, ErrUserInactive, err)
assert.Nil(t, pair)
assert.Nil(t, u)
}
func TestAuthService_Login_WrongUsername(t *testing.T) {
db := testutil.SetupTestDB()
hotel := testutil.CreateTestHotel(db, "HOTEL005")
testutil.CreateTestUser(db, hotel.ID, "admin", "password123", "admin")
svc := NewAuthService(db)
pair, user, err := svc.Login("HOTEL005", "nonexistent", "password123")
assert.Error(t, err)
assert.Equal(t, ErrInvalidCredentials, err)
assert.Nil(t, pair)
assert.Nil(t, user)
}
func TestAuthService_RefreshTokens(t *testing.T) {
db := testutil.SetupTestDB()
hotel := testutil.CreateTestHotel(db, "HOTEL006")
testutil.CreateTestUser(db, hotel.ID, "admin", "password123", "admin")
svc := NewAuthService(db)
pair, _, err := svc.Login("HOTEL006", "admin", "password123")
require.NoError(t, err)
require.NotNil(t, pair)
// 用 refresh token 换新 token
newPair, err := svc.RefreshTokens(pair.RefreshToken)
require.NoError(t, err)
require.NotNil(t, newPair)
assert.NotEmpty(t, newPair.AccessToken)
assert.NotEmpty(t, newPair.RefreshToken)
}
func TestAuthService_RefreshTokens_Invalid(t *testing.T) {
db := testutil.SetupTestDB()
testutil.InitConfig()
svc := NewAuthService(db)
newPair, err := svc.RefreshTokens("invalid.token.here")
assert.Error(t, err)
assert.Nil(t, newPair)
}
func TestHashPassword(t *testing.T) {
hash, err := HashPassword("mypassword")
require.NoError(t, err)
assert.NotEmpty(t, hash)
assert.NotEqual(t, "mypassword", hash)
// 第二次哈希应不同(bcrypt 加 salt
hash2, err := HashPassword("mypassword")
require.NoError(t, err)
assert.NotEqual(t, hash, hash2)
}
func TestInitConfig(t *testing.T) {
testutil.InitConfig()
}
func init() {
testutil.InitConfig()
}