草庐IT

javascript - 有没有一种惯用的方法来测试嵌套状态分支?

coder 2024-05-13 原文

假设我有一个具有多个分支的 reducer,但每个分支都足够相似,可以使用工厂函数生成。所以,我创建了一个:

import { combineReducers } from 'redux'

const createReducerScope = scopeName => {
  const scope = scopeName.toUpperCase()

  const contents = (state = {}, action) => {
    switch (action.type) {
      case `${scope}_INSERT`:
        return { ...state, [action.id]: action.item }
      default:
        return state
    }
  }

  const meta = (state = {}, action) => {
    switch (action.type) {
      case `${scope}_REQUEST`:
        return { ...state, requesting: true }
      case `${scope}_REQUEST_FAILURE`:
        return {
          ...state,
          requesting: false,
          errorMessage: String(action.error)
        }
      case `${scope}_REQUEST_SUCCESS`:
        return {
          ...state,
          requesting: false,
          errorMessage: null
        }
      default:
        return state
    }
  }

  return combineReducers({ contents, meta })
}

我用它来组成一个更大的根级状态树:

const products = createReducerScope('products')
const orders = createReducerScope('orders')
const trades = createReducerScope('trades')

const rootReducer = combineReducers({ products, orders, trades })

这应该给我一个看起来像这样的状态图:

{
  products: { contents, meta },
  orders: { contents, meta },
  trades: { contents, meta }
}

如果我想测试这个状态,我的第一直觉是在我的测试套件中创建这个范围的一个版本,然后测试那个隔离的 reducer(只是针对 contentsmeta 分支)。

这里的复杂之处在于我正在尝试测试选择器,我读过的所有选择器设计似乎都暗示了以下两点:

  1. 您通过将选择器和缩减器放在同一个文件中来封装您的状态。
  2. mapStateToProps 应该只需要知道两件事,全局状态和相关的选择器。

所以这是我的问题:将这些或多或少组成的 reducer 与根级别相关的选择器配对在一起,使我的测试样板文件变得有点厚。

更不用说具有整个树知识的硬写选择器感觉它违背了 reducer 模块化尝试的要点。

我 100% 确定我遗漏了一些明显的东西,但我真的找不到任何示例代码来演示测试模块化缩减器和选择器的方法。

如果选择器通常应该知道整个全局状态,但您有高度组合的缩减器,是否有一种干净、惯用的方法来测试它?或者可能是更具可组合性的选择器设计?

最佳答案

并置选择器和缩减器的要点是一个文件中的缩减器和选择器应该在相同的状态形状上运行。如果您将 reducer 拆分为多个文件来组合它们,您应该对您的选择器执行相同的操作。

您可以在我的 new Egghead series 中看到这方面的示例(视频 1020 可能特别有用)。

所以你的代码应该更像

const createList = (type) => {
  const contents = ...
  const meta = ...
  return combineReducers({ contents, meta })
}

// Use default export for your reducer
// or for a reducer factory function.
export default createList

// Export associated selectors
// as named exports.
export const getIsRequesting = (state) => ...
export const getErrorMessage = (state) => ...

然后,您的 index.js 可能看起来像

import createList, * as fromList from './createList'

const products = createList('products')
const orders = createList('orders')
const trades = createList('trades')

export default combineReducers({ products, orders, trades })

export const getIsFetching = (state, type) =>
  fromList.getIsFetching(state[type])

export const getErrorMessage = (state, type) =>
  fromList.getErrorMessage(state[type])

这样根选择器委托(delegate)给子选择器,就像根缩减器委托(delegate)给子缩减器一样。在每个文件中,选择器中的state 对应于导出的reducer 的state,state shape 实现细节不会泄露到其他文件。

最后,为了测试那些 reducer/selector 包,你可以做类似的事情

import createList, * as fromList from './createList')

describe('createList', () => {
  it('is not requesting initially', () => {
    const list = createList('foo')
    const state = [{}].reduce(list)
    expect(
      fromList.isRequesting(state)
    ).toBe(false)
  })

  it('is requesting after *_REQUEST', () => {
    const list = createList('foo')
    const state = [{}, { type: 'foo_REQUEST' }].reduce(list)
    expect(
      fromList.isRequesting(state)
    ).toBe(true)
  })
})

关于javascript - 有没有一种惯用的方法来测试嵌套状态分支?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37647178/

有关javascript - 有没有一种惯用的方法来测试嵌套状态分支?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  6. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  7. Ruby 方法() 方法 - 2

    我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby​​-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco

  8. ruby - 难道Lua没有和Ruby的method_missing相媲美的东西吗? - 2

    我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/

  9. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  10. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

随机推荐