开玩笑单元测试检查唯一值

Posted

技术标签:

【中文标题】开玩笑单元测试检查唯一值【英文标题】:Jest Unit Test check for unique value 【发布时间】:2021-05-09 20:26:36 【问题描述】:

我是单元测试的新手,并为我的组件和类编写它们。 我有一种过滤重复数字但具有相同 ID 的方法。 我写了这个方法:

public groupByOrderNumber(
    deliveryReceipts: DeliveryReceiptSearch[]
): Map<string, Map<string, DeliveryReceiptItemSearchResult[]>> 
    const groupedDeliveryReceipts = new Map<string, Map<string, DeliveryReceiptItemSearchResult[]>>();

    for (const receipt of deliveryReceipts) 
        const receiptId: string = receipt.id;
        groupedDeliveryReceipts.set(receiptId, new Map<string, DeliveryReceiptItemSearchResult[]>());
        for (const item of receipt.items) 
            const orderNumber = item.orderNumber;
            if (groupedDeliveryReceipts.get(receiptId).has(orderNumber)) 
                groupedDeliveryReceipts.get(receiptId).get(orderNumber).push(item);
             else 
                groupedDeliveryReceipts.get(receiptId).set(orderNumber, [item]);
            
        
    

    return groupedDeliveryReceipts;

我的测试是这样的:

describe('groupByOrderNumber', () => 
    const deliveryReceipts: DeliveryReceiptSearchMock[] = DeliveryReceiptSearchMock.createListOfReceipts();

    it('should not contain identical orderNumbers', () => 
        const dReceipts: Map<string, Map<string, DeliveryReceiptItemSearchResult[]>> = service.groupByOrderNumber(
            deliveryReceipts
        );

        for (const receipts of deliveryReceipts) 
            const receiptId: string = receipts.id;
            for (const item of receipts.items) 
                const orderNumber = item.orderNumber;
                expect(dReceipts.get(receiptId).has(orderNumber)).toIn
          expect(dReceipts.get(receipts.id).set(orderNumber, [item])).not.toEqual(dReceipts.get(receipts.id).get(orderNumber));
            
        
    );
);

测试将模拟一些数据以用于测试,如开头所示。 我不太确定如何测试 orderNumber 是否是其 receipt.id 独有的。

有没有办法使用一些原生的 jest 方法?

例子:

receipt.id ('9876') -> orderNumber ('123')
receipt.id ('101112') -> orderNumber ('123')

groupByOrderNumber() 基本上就是这样做的。

【问题讨论】:

仍在学习 Jest,但您可以尝试从空数组开始,然后检查数组中是否存在订单号。类似于:expect(testArray).not.toContain(orderNumber)。如果没有失败,则将该订单号添加到数组中。 是的,我明白你的想法。我希望orderNumber 存在于数组中,但我希望它对于相应的receipt.id 是唯一的。就像我有两张收据,orderNumber 相同,receipt.id 不同。 你能在 stackblitz 或类似的东西中重新创建它吗?它使帮助变得更容易,并且可能更详细地说明您当前的测试用例做了什么以及结果与您的预期有何不同 【参考方案1】:

首先,您需要创建一个按 id 存储收据的地图,这样您就可以非常轻松地访问具有相同 id 的所有收据。

然后,对于每个收据 id,获取订单号。

最后,检查这些订单号是否唯一(将数组转换为 Set 并比较它们的长度)。

const deliveryReceipts = [
  id: '1',
  orderNumber: '123'
, 
  id: '1',
  orderNumber: '234'
, 
  id: '2',
  orderNumber: '123'
, 
  id: '3',
  orderNumber: '456'
, 
  id: '3',
  orderNumber: '456'
];
const receiptsMap: 
  [id: string]: DeliveryReceiptSearchMock[]
 = ;

// This iterates over every receipt and stores them in a map based on their ID.
for (const receipt of deliveryReceipts) 
  const receiptId: string = receipt.id;
  receiptsMap[receiptId] = [...receiptsMap[receiptId] || [], receipt];


// For each receiptId, let's test if the orderNumbers are unique.
for (const receiptId of Object.keys(receiptsMap)) 
  const allOrderNumbers = receiptsMap[receiptId].map((receipt) => receipt.orderNumber);
  const uniqueOrderNumbers = [...new Set(allOrderNumbers)];
  // expect(allOrderNumbers.length).toBe(uniqueOrderNumbers.length)
  expectToEqual(receiptId, allOrderNumbers.length, uniqueOrderNumbers.length);


function expectToEqual < T > (receiptId: string, given: T, expected: T): void 
  if (given === expected) 
    console.log(`id $receiptId ✓`);
   else 
    console.log(`id $receiptId ✗ Expected $expected but found $given`);
  

【讨论】:

【参考方案2】:

如果您在检查订单号的嵌套字典上看到重复的标识符,您可以创建一个嵌套字典并立即失败。

通过这种方式,我们避免在整个集合中循环多次。

function testReceipts(deliveryReceipts) 
  const orderCheck = 
  for (const receipt of deliveryReceipts) 
    orderCheck[receipt.id] = Boolean(orderCheck[receipt.id]) ? orderCheck[receipt.id] : ;
    for (const item of receipt.items) 
      const orderNumber = item.orderNumber;
      expect(!orderCheck[receipt.id].hasOwnProperty(orderNumber)).toBeTruthy();
      orderCheck[receipt.id][orderNumber] = ""
    
  

我写了一个小存根来运行 testReceipts 测试

// arrange
const knownGood = [
    id: 1,
    items: [
      orderNumber: 1
    , 
      orderNumber: 2
    , 
      orderNumber: 3
    ]
  ,
  
    id: 2,
    items: [
      orderNumber: 1
    , 
      orderNumber: 2
    , 
      orderNumber: 3
    ]
  
];

const knownBad = [
    id: 1,
    items: [
      orderNumber: 1
    , 
      orderNumber: 2
    , 
      orderNumber: 1
    ]
  ,
  
    id: 2,
    items: [
      orderNumber: 1
    , 
      orderNumber: 2
    , 
      orderNumber: 3
    ]
  
];

// assert
testReceipts(knownGood); // pass.
testReceipts(knownBad); // Bad code, bad!

// I didn't want to install Jest, so I made my own little expect wrapper. You'd obviously use Jest.
function expect(arg) 
  return (
    toBeTruthy: () => 
      if (!Boolean(arg)) console.error("Bad code, bad!");
    
  )



【讨论】:

以上是关于开玩笑单元测试检查唯一值的主要内容,如果未能解决你的问题,请参考以下文章

如果调用 super() 则开玩笑的单元测试

开玩笑单元测试返回“MongoError:拓扑被破坏”

createWriteStream 的 ('error') 上的开玩笑单元测试

调度程序没有在开玩笑的单元测试中注册回调

开玩笑的带有 expo sqlite 调用的单元测试类

如何对 fetch 完成后呈现的 React 组件进行单元测试?