import { Prisma } from '@prisma/client' const mockPositionFindMany = jest.fn() const mockExchangeRateFindMany = jest.fn() const mockSecurityFindMany = jest.fn() jest.mock('@/lib/prisma', () => ({ prisma: { position: { findMany: (...args: any[]) => mockPositionFindMany(...args), }, exchangeRate: { findMany: (...args: any[]) => mockExchangeRateFindMany(...args), }, security: { findMany: (...args: any[]) => mockSecurityFindMany(...args), }, }, })) import { GET } from '../src/app/api/positions/route' describe('Positions API - GET', () => { beforeEach(() => { jest.clearAllMocks() }) it('返回空数组当无持仓', async () => { mockPositionFindMany.mockResolvedValue([]) mockExchangeRateFindMany.mockResolvedValue([]) mockSecurityFindMany.mockResolvedValue([]) const req = new Request('http://localhost/api/positions') const res = await GET(req) expect(res.status).toBe(200) const data = await res.json() expect(data).toEqual([]) }) it('返回持仓列表及市值计算', async () => { const mockPositions = [ { id: 'pos-1', accountId: 'acc-1', symbol: 'AAPL', quantity: new Prisma.Decimal('10'), averageCost: new Prisma.Decimal('150'), currency: 'USD', account: { name: '美股账户', marketType: 'US' as const }, }, { id: 'pos-2', accountId: 'acc-2', symbol: 'BTC', quantity: new Prisma.Decimal('0.5'), averageCost: new Prisma.Decimal('50000'), currency: 'USD', account: { name: '加密账户', marketType: 'CRYPTO' as const }, }, ] const mockSecurities = [ { symbol: 'AAPL', name: 'Apple Inc', lotSize: 1, priceDecimals: 2, isCrypto: false }, { symbol: 'BTC', name: 'Bitcoin', lotSize: 1, priceDecimals: 2, isCrypto: true }, ] mockPositionFindMany.mockResolvedValue(mockPositions) mockExchangeRateFindMany.mockResolvedValue([]) mockSecurityFindMany.mockResolvedValue(mockSecurities) const req = new Request('http://localhost/api/positions') const res = await GET(req) expect(res.status).toBe(200) const data = await res.json() expect(data).toHaveLength(2) expect(data[0]).toMatchObject({ symbol: 'AAPL', quantity: '10', averageCost: '150', currency: 'USD', accountName: '美股账户', marketType: 'US', isCrypto: false, }) expect(data[1]).toMatchObject({ symbol: 'BTC', quantity: '0.5', averageCost: '50000', currency: 'USD', accountName: '加密账户', marketType: 'CRYPTO', isCrypto: true, }) }) it('按accountId过滤持仓', async () => { mockPositionFindMany.mockResolvedValue([]) mockExchangeRateFindMany.mockResolvedValue([]) mockSecurityFindMany.mockResolvedValue([]) const req = new Request('http://localhost/api/positions?accountId=acc-1') await GET(req) expect(mockPositionFindMany).toHaveBeenCalledWith( expect.objectContaining({ where: { accountId: 'acc-1' }, }) ) }) })