单元测试中的部分模拟/伪造

时间:2014-02-27 22:38:32

标签: c# unit-testing mocking fakeiteasy

我有一个关于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
}

现在,我必须为该类编写一些单元测试代码。当我真的用baseMethod()测试Checkservice()时,是否可以模拟GetBoolean()?如果没有,我应该如何修改代码?

谢谢, 凯尔

3 个答案:

答案 0 :(得分:3)

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

但是在你的方法中,我认为你可以在没有任何模拟的情况下做到这一点。 我希望这会有所帮助!

答案 1 :(得分:3)

即使这是可能的,也很可能是一个坏主意。单元测试CheckService应仅测试CheckService,而不是GetbooleanGetboolean应该有一个单独的单元测试,它不依赖于任何其他方法。

正确的方法是让你的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
}

然后在你的测试类中(使用Moq语法,抱歉我不知道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));
}

答案 2 :(得分:2)

通常Self Mocking是一个承担过多责任的阶级的标志。更聪明的想法是打破你想要自我模拟的不同部分的其他类,并将这些类注入你的。查找dependency injection

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

自我嘲弄的一般想法是这样的:

你对你的班级进行“测试”测试,这扩展了你的班级。然后将你想要的功能用于测试。

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

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

然后您的测试代码将使用该类作为对象的存根版本。