You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行Cucumber时如何Mock服务/控制器内的Zendesk库

解决方案:在Cucumber验收测试中Mock Zendesk库

核心思路是复用单元测试的依赖注入逻辑,在验收测试层将真实Zendesk客户端替换为Mock实现,同时结合Cucumber步骤定义动态控制Mock行为,既避免真实API调用成本,又保证验收测试的流程完整性。

具体实现步骤

1. 抽象Zendesk操作接口

先让业务代码依赖抽象接口而非具体库实现,这样才能无缝替换为Mock:

// 定义业务需要的Zendesk操作接口
type ZendeskTicketService interface {
    CreateTicket(ticket *zendesk.Ticket) (*zendesk.Ticket, error)
    GetTicket(ticketID int64) (*zendesk.Ticket, error)
}

// 真实客户端实现该接口
type RealZendeskService struct {
    client *zendesk.Client
}

func (s *RealZendeskService) CreateTicket(ticket *zendesk.Ticket) (*zendesk.Ticket, error) {
    return s.client.Tickets.Create(context.TODO(), ticket)
}

func (s *RealZendeskService) GetTicket(ticketID int64) (*zendesk.Ticket, error) {
    return s.client.Tickets.Show(context.TODO(), ticketID)
}

2. 编写Mock实现

基于接口写轻量Mock(也可以用GoMock自动生成,手动实现更适合验收测试中动态调整):

type MockZendeskService struct {
    CreateFunc func(*zendesk.Ticket) (*zendesk.Ticket, error)
    GetFunc    func(int64) (*zendesk.Ticket, error)
}

func (m *MockZendeskService) CreateTicket(ticket *zendesk.Ticket) (*zendesk.Ticket, error) {
    return m.CreateFunc(ticket)
}

func (m *MockZendeskService) GetTicket(ticketID int64) (*zendesk.Ticket, error) {
    return m.GetFunc(ticketID)
}

3. 在Cucumber流程中注入并控制Mock

在测试初始化阶段替换真实服务为Mock,然后在步骤定义里设置Mock的返回逻辑:

var mockZendesk *MockZendeskService

func init() {
    // 初始化Mock并注入到业务逻辑的依赖中(比如全局服务容器或构造函数)
    mockZendesk = &MockZendeskService{}
    app.SetZendeskService(mockZendesk)
}

// Given步骤:预设创建工单的Mock返回
Given(`^创建工单时返回ID为(\d+)的工单$`, func(ticketID int64) error {
    mockZendesk.CreateFunc = func(t *zendesk.Ticket) (*zendesk.Ticket, error) {
        return &zendesk.Ticket{ID: ticketID, Subject: t.Subject}, nil
    }
    return nil
})

// When步骤:执行业务创建工单操作
When(`^用户提交主题为"([^"]*)"的工单$`, func(subject string) error {
    _, err := app.CreateTicket(subject)
    return err
})

// Then步骤:验证查询工单的结果
Then(`^查询ID为(\d+)的工单应返回主题"([^"]*)"$`, func(ticketID int64, expectedSubject string) error {
    mockZendesk.GetFunc = func(id int64) (*zendesk.Ticket, error) {
        if id != ticketID {
            return nil, fmt.Errorf("unexpected ticket ID: %d", id)
        }
        return &zendesk.Ticket{ID: ticketID, Subject: expectedSubject}, nil
    }
    ticket, err := app.GetTicket(ticketID)
    if err != nil {
        return err
    }
    if ticket.Subject != expectedSubject {
        return fmt.Errorf("expected subject %s, got %s", expectedSubject, ticket.Subject)
    }
    return nil
})

4. 备选方案:本地API Mock服务器

如果需要更贴近真实API的行为,可以启动WireMock、MockServer这类本地Mock服务,修改Zendesk客户端的BaseURL指向本地地址:

client, _ := zendesk.NewClient(nil)
client.BaseURL = "http://localhost:8080/api/v2" // 指向本地Mock服务

然后在Cucumber步骤中配置Mock服务器的响应规则,比如设定创建工单返回指定ID、查询工单返回对应数据,这种方式无需修改业务代码,Mock行为更接近真实场景。

关键注意事项

  • 虽然验收测试优先真实依赖,但API调用有成本时,Mock是合理选择,需保证Mock行为与真实API一致
  • 建议定期运行少量真实API的验收测试,验证Mock逻辑的准确性
  • 依赖注入是核心前提,必须确保业务代码不直接耦合具体Zendesk客户端实现

内容的提问来源于stack exchange,提问作者HexaCrop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 07:13:13