单元测试中要不要模拟每一个依赖关系?

问题描述 投票:0回答:1

看了很多书,发现大家都建议在单元测试中模拟方法中的每一个依赖关系。

在单元测试时,我应该模拟所有的依赖关系吗?

什么时候应该mock?

然而,我有一个方法,它创建了一个对象列表(依赖关系),并使用该方法来改变这些对象的列表。在实际场景中,该方法正在将客户端发送的数据有效载荷转化为这些对象.下面是Typescript中的代码实现,但它只是给你一个想法。

import {expect} from 'chai';

import 'mocha';

class Bar {
    private val: number;

    constructor(val: number) {
        this.val = val;
    }

    isValid(): boolean {
        return this.val !== 2;
    }

    canMergeWith(bar: Bar): boolean {
        return this.val === bar.val;
    }
}

class BarBuilder {
    constructor() {
    }

    createBars(payload: number[]): Bar[] {
        const bars: Bar[] = [];
        payload.forEach(p => {
            bars.push(new Bar(p));
        });

        const filtered = this.filterBars(bars);
        const merged = this.mergeBars(filtered);
        return merged;
    }

    private filterBars(bars: Bar[]): Bar[] {
        return bars.filter(b => b.isValid());
    }

    private mergeBars(bars: Bar[]): Bar[] {
        const merged: Bar[] = [];
        bars.forEach((bar, i) => {
            if (i > 0) {
                const before = bars[i - 1];
                if (!bar.canMergeWith(before)) {
                    merged.push(bar);
                }
            } else {
                merged.push(bar);
            }
        });
        return merged;
    }
}

describe('BarBuilder', () => {
    it('Should convert payload into valid bars', () => {
        const payload = [1, 2, 3, 4, 4, 5, 5];
        const barBuilder = new BarBuilder();
        const bars = barBuilder.createBars(payload);
        expect(bars).to.deep.equal([{val: 1}, {val: 3}, {val: 4}, {val: 5}]);
    });
});

目前,测试是通过的。但它违反了以下规则 我应该模拟类中的每一个依赖关系.

我的问题是,我应该做以下哪一个。

  1. 我真的应该模拟班级的吧,以遵守该规则?

如果是这样,我发现这样做还有一个困难。如果我模拟Bar类,我如何使模拟方法成为 canMergeWithisValid 根据他们的输入返回true或false?是不是相当于重写了类本身?

  1. 我是不是应该重构我的代码呢?

我也在想可能问题出在我的代码不可测试上。之前,我的方法 canMergeWithisValid 属于 BarBuilder. 为了便于阅读,我把它们移到了Bar里面。但现在,单元测试 BarBuilder 不再是小事了。

  1. 尽管测试违反了单元测试规则,但还是要保持原样。
unit-testing oop language-agnostic
1个回答
2
投票

我发现人们建议在单元测试中模拟方法中的所有依赖关系。

有些人建议这样做,是的。在链接的帖子中,更多的人不同意。单元测试其实是一个有分歧的话题。

当我第一次了解到没有一个被整个行业广泛接受的单元测试定义时,我很惊讶。人们经常谈论单元测试,好像只有一个定义,特别是 "模拟一切 "的定义;但如果你读过链接的线程,你会发现这种方法有很多陷阱,特别是那些测试的脆弱性。

我认为 "模拟一切 "的定义之所以还能如此泛滥,是因为它是如此的微不足道。不涉及任何思考,只是模拟一切。另一种选择是考虑什么时候该嘲讽,什么时候不该嘲讽。这就比较难了。你必须证明模拟的合理性。把单元测试定义为 "模拟一切 "比较容易,因为这样你就不用考虑模拟的目的是什么。这只是定义的一部分。

Ian Cooper 在TDD的背景下,Kent Beck定义了单元测试,并发表了一篇关于单元测试的演讲。我发现他的观点比 "mock一切 "的方法更现代。

我的建议是:当它们对你有帮助时,就创建mock。不要为了满足一个规则而创建mock。没有什么规则背后是有共识的。

© www.soinside.com 2019 - 2024. All rights reserved.