2009-09-02 131 views
21

我有一个名为TestMakeAValidCall()的单元测试。它测试我的手机应用程序进行有效的通话。单元测试 - 是否有单元测试调用其他单元测试的不良形式

我即将编写另一个测试,名为TestShowCallMessage(),需要有一个有效的测试呼叫。在该测试中打电话给TestMakeAValidCall()是不是很糟糕?

供参考这是我的TestMakeAValidCall()测试。

[TestMethod] 
    public void TestMakeAValidCall() 
    { 
     //Arrange 
     phone.InCall = false; 
     phone.CurrentNumber = ""; 
     // Stub the call to the database 
     data.Expect(x => x.GetWhiteListData()). 
      Return(FillTestObjects.GetSingleEntryWhiteList()); 
     // Get some bogus data 
     string phoneNumber = FillTestObjects.GetSingleEntryWhiteList(). 
      First().PhoneNumber; 
     // Stub th call to MakeCall() so that it looks as if a call was made. 
     phone.Expect(x => x.MakeCall(phoneNumber)). 
      WhenCalled(invocation => 
         { 
          phone.CurrentNumber = phoneNumber; 
          phone.InCall = true; 
         }); 

     //Act 
     // Select the phone number 
     deviceControlForm.SelectedNumber = phoneNumber; 
     // Press the call button to make a call. 
     deviceMediator.CallButtonPressed(); 

     //Assert 
     Assert.IsTrue(phone.InCall); 
     Assert.IsTrue(phone.CurrentNumber == phoneNumber); 
    } 
+0

感谢所有的好的答案。我将重复代码重构为单独的调用。我以最多的选票选出答案。 – Vaccano 2009-09-02 17:17:19

回答

51

将设置重构为另一个方法并从两个测试中调用该方法。测试不应该调用其他测试。

+3

不要用测试测试另一个测试 – 2013-02-11 11:05:00

+0

在这种情况下,有人可以精心研究重构的样子吗? – 2015-11-28 15:33:25

+1

@Nakata - 很难在不知道依赖关系是如何构造的情况下显示这个示例的确切代码,但是这个要点显示了我用来将代码设置在测试环境中并在多个测试中从那里调用它的模式。 https://gist.github.com/tvanfosson/1ca6dd3bb0b796de65b0 – tvanfosson 2015-11-28 16:10:41

6

我认为它是一个坏主意。你希望你的单元测试只测试一件事情和一件事情。不要通过其他测试创建一个呼叫,而应该嘲笑一个呼叫并将其作为参数传递。

11

恕我直言,你应该做下列之一:

  • 创建一个返回的有效调用的方法,并分别用其来进行测试(而不是一个调用其它)
  • 模拟的有效通话ShowCallMessageTest
4

单元测试应根据定义测试代码的一个单元/函数。调用其他单元测试使其测试多个单元。我把它分解成单独的测试。

2

是的 - 单元测试应该是分开的,应该只测试一件事情(或者至少少数几件紧密相关的事情)。顺便说一句,在您的测试方法的调用data.Expect和phone.Expect创建的预期,而不是存根调用,它可以使你的测试脆弱,如果你重构......

+0

感谢您对我的术语进行更正。我已经更新了我的源代码中的评论。 – Vaccano 2009-09-02 17:18:16

6

提供了一个反衬点:

我坚信精心设计的单元测试应该是互相依赖!

当然,只有当测试框架知道这些依赖关系时,才有意义,这样当依赖关系失败时,它可以停止运行依赖测试。更好的是,这样的框架可以将测试夹具从测试传递到测试,这样就可以建立在不断增长和扩展的夹具上,而不是从头开始重新构建每一个测试。当然,缓存完成时要注意,如果多个测试取决于同一个示例,则不会引入副作用。

我们在JExample extension for JUnit中实现了这个想法。目前还没有C#端口,但有端口RubySmalltalk和... most recent release of PHPUnit picked up both our ideas: dependencies and fixture reuse

PS:folks are also using it for Groovy

+0

有意思的是,如果做得对,它可以减少重复很多。 – 2010-02-19 12:20:05

1

单元与模块....我们也认为测试也应该依赖于可重用的方法,并且应该在api级别的测试集成类中进行测试。许多人只是测试一个班,但许多错误是在班级之间的整合。我们也使用verifydesign来保证api不依赖于实现。这允许你在不触及测试的情况下重构整个组件/模块(我们经历了一次,实际上它运行得很好)。当然,任何体系结构的变化都会迫使你重构测试,但至少模块中的设计变更不会导致测试重构的工作(除非你改变api的行为,当然这比隐瞒地发射更多的事件,无论如何,“将是一个API变化)。