国家/互动测试和混乱的混合(或滥用)他们(State/Interaction testing and

2019-08-01 17:15发布

我想了解国家基础/交互测试的定义(读福勒的东西,等等)。 我发现,我开始基于状态的,但更多的互动基础一直在做,我得到了如何测试某些事情有点困惑。

我在MVC控制器和行动电话服务拒绝包:

public ActionResult Deny(int id)
{
    service.DenyPackage(id);

    return RedirectToAction("List");
}

这似乎昭示着我。 提供一个模拟服务,验证它是正确调用,完成。

现在,我有一个观点,即让用户的证书与包关联的动作:

public ActionResult Upload(int id)
{
    var package = packageRepository.GetPackage(id);
    var certificates = certificateRepository.GetAllCertificates();

    var view = new PackageUploadViewModel(package, certificates);

    return View(view);
}

这一次我有点难倒。 我做的规格样式的测试(可能是不正确的),所以测试这个方法我有一个类,然后两个测试:验证包库叫,验证证书库被调用。 其实我是想第三个测试,以验证该构造函数被调用,但不知道该怎么做! 我得到的印象,这是完全错误的。

因此,对于基于状态的测试中,我将通过在ID,然后测试的ActionResult的看法。 好吧,这是有道理的。 但不会我对PackageUploadViewModel构造一个测试? 所以,如果我在构造一个测试,然后我的一部分将只是想确认我调用构造函数和动作相匹配的回报是什么构造函数返回。

现在,我能想到的另一个选择是我有一个PackageUploadViewModelBuilder(或者同样默默命名)具有在两个仓库的依赖,然后我只是通过将ID CreateViewModel方法什么的。 然后,我可以嘲笑这个对象,验证一切,并很高兴。 但是......嗯......看来奢侈。 我正在做一些简单的...不是简单的。 此外,controller.action(ID)返回builder.create(ID)似乎是增加了一层无缘无故(控制器负责构建视图模型..吧?)

我不知道......我想更多的基于状态的测试是必要的,但我怕如果我开始测试的返回值那么如果A法可以得到所谓的在8个不同的上下文中,我将有一个测试爆炸了很多重复。 我一直在使用基于交互测试,通过一些这些上下文方法B,使所有我需要做的就是验证方法A调用方法B和我有方法B测试,因此方法A可以只相信那些上下文处理。 因此,基于交互测试正在建设的测试,但基于状态的测试是要压平了一些这个层次。

我不知道如果作出任何意义。

哇,这是长...

Answer 1:

我认为罗伊Osherove最近挖苦,作为一个经验法则,你的测试应该是95%的国家本位和5%的相互作用为基础的。 我同意。

最重要的是,你的API做你希望它是什么, 就是你需要测试的内容。 如果你测试它如何实现它所需要做的机制,你很可能与Overspecified测试,这会咬你的时候还可维护性结束。

在大多数情况下,你可以设计自己的API,使基于状态的测试是自然的选择,因为这就是这么多了。

要检查您的上传例如:它的问题是GetPackage和GetAllCertificates叫? 事实是否真的上传方法的预期结果?

我猜不会。 我的猜测是,上传方法的目的 - 这是非常存在的理由 - 是填充和服务于正确的观点。

因此,基于状态的测试将检查返回的ViewResult和视图模型,并验证它拥有所有正确的价值观。

当然,作为代码表示,现在,你需要为packageRepository和certificateRepository提供测试双打,否则异常将被抛出,但它并不像它本身就是重要的资源库方法被调用。

如果你使用存根,而不是嘲笑你的仓库,你的测试不再依赖于内部实现细节。 如果您稍后决定更改上传方法的实现,使用的包(或其他)的高速缓存的实例,存根将不会被调用,不过没关系,因为这并不重要-重要的返回的视图中包含预期的数据。

这比即使所有返回的数据是理所应当的试验中断裂更preferrable。

有趣的是,你拒绝的例子看起来是一个典型的例子,其中的相互作用为基础的测试仍在合理的,因为只有通过检查间接输出,你可以验证的方法进行正确的动作(DenyPackage方法返回void)。

所有这一切,更多的,是在优秀的书很好的解释的xUnit测试模式 。



Answer 2:

要问的问题是:“如果这个代码工作,我怎么会知道?” 这可能意味着测试一些相互作用或一些状态,这取决于什么是重要的。

在首次测试中, Deny改变目标类以外的世界。 它需要从服务合作,所以测试的交互是有道理的。 在你的第二个测试,你对邻居(不改变目标类以外的任何东西)进行查询,因此磕碰他们更有意义。

这就是为什么我们有“存根查询,模拟操作”的启发式http://www.mockobjects.com/book



文章来源: State/Interaction testing and confusion on mixing (or abusing) them