douyu1990 2019-08-14 01:22
浏览 94
已采纳

从常量初始化变量并进行一些更改

I'm trying to create some scenarios for unit testing purposes and running into some problems when dealing with complex objects that I'd like to start from a base state.

In the below example is a simplified case where we have a query builder that may take three parameters. In this case we must always supply all three parameters to avoid a NPE when trying to access a reference.

package main

import (
  "fmt"
)

type Searcher struct {
  Param string
}

type CompleteSearcher struct {
  A *Searcher
  B *Searcher
  C *Searcher
}

func (c *CompleteSearcher) FormatQuery() string {
  return fmt.Sprintf("%s%s%s", c.A.Param, c.B.Param, c.C.Param)
}

func main() {
  testCases := []struct {
    scenario string
    want string
    searcher *CompleteSearcher
  }{
    {
      scenario: "A populated",
      want: "A",
      searcher: &CompleteSearcher{
          A: &Searcher{Param: "A"},
          B: &Searcher{},
          C: &Searcher{},
        },
    },
  }

  for _, tc := range testCases {
    got := tc.searcher.FormatQuery()
    if got != tc.want {
      fmt.Println("error")
    }
  }
}

My specific problem with this is mostly that the scenario must initialize all fields creating a noisy test where it's somewhat unclear what's actually under test. You can imagine with even more searchable fields, cache classes, backend classes, etc. that a simple enough function can have an enormous object responsible for actually doing the setup.

So what I'd like to do instead is something like the following.

baseSearcher := &CompleteSearcher{
  A: &Searcher{},
  B: &Searcher{},
  C: &Searcher{},
}
testCases := []struct {
  scenario string
  want string
  searcher *CompleteSearcher
}{
  {
    scenario: "A populated",
    want: "A",
    searcher: New(baseSearcher){A: &Searcher{Param: "A"}}
  },
}

Essentially I'd like to be able to test an entire object, but have the option to start with a "base" version of that object to prevent repeated setup in each scenario setup. From what I can tell there's no way to create a copy (even a shallow-copy) and then also do another assignment in a single statement, making it effectively impossible to have each scenario handle the object directly.

Any tips on how to resolve this issue?

  • 写回答

1条回答 默认 最新

  • douwang9650 2019-08-14 01:48
    关注

    If you are really wanting the one-liner, you could do something like

    func NewCS() *CompleteSearcher {
        return &CompleteSearcher{
            A:     &Searcher{},
            B:     &Searcher{},
            C:     &Searcher{},
            Cache: &Cacher{cache: make(map[string]interface{})},
        }
    }
    
    func (c *CompleteSearcher) WithA(s *Searcher) *CompleteSearcher {
        c.A = s
        return c
    }
    
    func (c *CompleteSearcher) WithB(s *Searcher) *CompleteSearcher {
        c.B = s
        return c
    }
    
    func (c *CompleteSearcher) WithC(s *Searcher) *CompleteSearcher {
        c.C = s
        return c
    }
    
    func (c *CompleteSearcher) WithCacher(s *Cacher) *CompleteSearcher {
        c.Cache = s
        return c
    }
    

    Playground example

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 ogg dd trandata 报错
  • ¥15 高缺失率数据如何选择填充方式
  • ¥50 potsgresql15备份问题
  • ¥15 Mac系统vs code使用phpstudy如何配置debug来调试php
  • ¥15 目前主流的音乐软件,像网易云音乐,QQ音乐他们的前端和后台部分是用的什么技术实现的?求解!
  • ¥60 pb数据库修改与连接
  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?
  • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?
  • ¥20 神经网络Sequential name=sequential, built=False
  • ¥16 Qphython 用xlrd读取excel报错