2014-02-27 68 views
3

我对FakeItEasy(或其他模拟对象,因为我相信它们很相似)有疑问。以下是我的puesdocode:单元测试中的部分嘲弄/伪造

public class Service 
{ 
    public void CheckService() 
    { 
     ... 
     Status status; 

     if (Getboolean) 
     { 
      status = Status.Pass; 
     } 
     else 
     { 
      status = Status.NotPass; 
     } 
    } 

    public bool Getboolean() 
    { 
     ..... 

     if (someConditions) 
      return true; 
     else 
      return false; 
    } 
} 

public enum Status 
{ 
    Pass = 0, 
    NotPass = 1 
} 

现在,我将不得不为该类编写一些单元测试代码。是否有可能嘲笑GetBoolean(),而我真的用baseMethod()测试Checkservice()?如果不是,我应该如何修改代码?

感谢, 凯尔

+0

这非常接近最近提出的[使用FakeItEasy方法来模拟方法](http://stackoverflow.com/questions/21733861/mocking-a-method-within-a-method-with-fakeiteasy ),其中我解释了如何去做你所要求的。但是,我仍然与其他人一起争论,这可能不是一个好主意。 –

+0

布莱尔康拉德,它非常接近!谢谢(你的)信息。 (并且在我发布之前,我猜我必须更努力地寻找类似的东西!!)。 – Kyle

回答

3

那么,即使这是可能的,它可能是一个坏主意。单元测试CheckService应该只测试CheckService,而不是Getboolean。对于Getboolean应该有一个单独的单元测试,它不依赖于任何其他方法。

正确的做法是将您的Getboolean放在继承自接口的不同类中,然后将该接口传递给Service构造函数(可能使用依赖注入),然后您可以嘲笑该接口并通过模拟实现在你的单元测试中。

例子:

public interface ILogicChecker 
{ 
    bool Getboolean(); 
} 

public class LogicChecker : ILogicChecker 
{ 
    public bool Getboolean() 
    { 
     //..... 

     if (someConditions) 
      return true; 
     else 
      return false; 
    } 
} 

public class Service 
{ 
    ILogicChecker logicChecker; 
    Status status; 

    public Service(ILogicChecker logicChecker) 
    { 
     this.logicChecker = logicChecker; 
    } 

    public void CheckService() 
    { 
     //... 

     if (logicChecker.Getboolean()) 
     { 
      status = Status.Pass; 
     } 
     else 
     { 
      status = Status.NotPass; 
     } 
    } 
} 

public enum Status 
{ 
    Pass = 0, 
    NotPass = 1 
} 

然后在您的测试类(使用起订量语法,对不起,我不知道FakeItEasy):

[Test] 
public void CheckService_WithTrueGetboolean_ShouldHave_PassStatus 
{ 
    //Arrange 
    var logicCheckerMock = new Mock<ILogicChecker>(); 
    logicCheckerMock.Setup(x => x.Getboolean()).Returns(true); 
    var service = new Service(logicCheckerMock.Object); 

    //Act 
    service.CheckService(); 

    //Assert 
    Assert.That(service.Status, Is.EqualTo(Status.Pass)); 
} 

[Test] 
public void CheckService_WithFalseGetboolean_ShouldHave_NotPassStatus 
{ 
    //Arrange 
    var logicCheckerMock = new Mock<ILogicChecker>(); 
    logicCheckerMock.Setup(x => x.Getboolean()).Returns(false); 
    var service = new Service(logicCheckerMock.Object); 

    //Act 
    service.CheckService(); 

    //Assert 
    Assert.That(service.Status, Is.EqualTo(Status.NotPass)); 
} 
+1

demoncodemonkey,帮助很多,谢谢! – Kyle

3

我认为这里没有什么嘲笑。 在我看来,Mock的主要目的是例如,如果你必须连接到数据库,那么你模拟知识库并返回你想要的数据而不连接到数据库。

但在你的方法中,我认为你可以做到没有任何模拟。 我希望这有助于!

+2

我同意这一点。你嘲笑你无法控制的项目,比如数据库的状态。 – paqogomez

+0

是啊! ;)你是对的paqogomez –

+0

模拟不一定是为了I/O操作。当单元测试一个调用另一个对象的方法时,你应该只关心你的方法在对象返回不同的值时做了什么。所以你会嘲笑对象的方法,因为你没有测试它。 – demoncodemonkey

2

一般Self Mocking是守住一类的标志责任太多。更聪明的想法是打破你想要自我模拟的不同部分的其他类,并将这些类注入到你的模型中。查查dependency injection

如果你真的需要这样做,但是这是可能的。我没有使用FakeItEasy,但是在MOQ中,您只需创建一个Mock<YourClass>,并将属性CallBase设置为true。

自我嘲讽的总体思路是这样的,但:

你让你的类,它扩展了您的类的“测试” verzion。然后确定你想要测试的功能。

public class TestServiceThatAlwaysReturnFalseForCheckBoolean : Service 
{ 
    public void CheckService() 
    { 
     base.CheckService() 
    } 

    public override bool Getboolean() 
    { 
     return false; 
    } 
} 

然后你的测试代码将使用该类作为对象的stubbed版本。