3

I have a question about FakeItEasy (or other mock objects since I belive they are pretty similiar). The following is my 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
}

Now, I would have to write some unit testing code for the class. Is it possible to mock GetBoolean() while I am really testing Checkservice() with the baseMethod()? If not, how should I modify the code?

Thanks, Kyle

Kyle
  • 406
  • 7
  • 20
  • This is very close to the recently-asked [Mocking a method within a method with FakeItEasy](http://stackoverflow.com/questions/21733861/mocking-a-method-within-a-method-with-fakeiteasy), in which I explain how to do what you ask. However, I still contend, with others here and there, that it's probably not a good idea. – Blair Conrad Feb 28 '14 at 12:48
  • Blair Conrad, It is very close! Thanks for the info. (and guess I will have to search harder for similar stuff before I post!!). – Kyle Feb 28 '14 at 15:26

3 Answers3

3

I think that here there is nothing to Mock. In my opinion, the main purpose of Mock is for example if you have to connecto to a database, then, you Mock the repository and return the data that you want without connect to the database.

But in your method, I think that you can do it without any Mock. i hope this helps!

Oscar Bralo
  • 1,912
  • 13
  • 12
  • 2
    I agree with this. You mock items that you cannot control, like the state of a database. – crthompson Feb 27 '14 at 22:45
  • Mocking doesn't have to be for I/O operations. When unit testing a method that calls another object, you should only care about what your method does when that object returns different values. So you would mock that object's methods because you're not testing that. – demoncodemonkey Feb 27 '14 at 22:56
  • Yeah, of course! I meant that the main purpose, but of course, you can Mock those methods to return the value that you want in order to tests only your main method. I meant that in this case, I think that is not neccesary! ;) – Oscar Bralo Feb 27 '14 at 22:57
3

Well even if that were possible, it is more than likely a bad idea. Unit testing CheckService should be testing CheckService only, not Getboolean. There should be a separate unit test for Getboolean which does not depend on any other method.

The correct way to do it would be to have your Getboolean in a different class which inherits from an interface, you would pass that interface into Service constructor (probably using dependency injection), then you could mock that interface and pass in the mock implementation in your unit tests.

Example:

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
}

Then in your test class (using Moq syntax, sorry I don't know 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));
}
demoncodemonkey
  • 11,730
  • 10
  • 61
  • 103
2

Generally Self Mocking is a sign of a class that hold onto too much responsibility. The smarter idea would be to break out other classes for the different parts you are wanting to self mock, and inject those classes into yours. look up dependency injection.

If you really need to do it though, it is possible. I have not used FakeItEasy, but in MOQyou just make a Mock<YourClass> with a property CallBase set to true.

The general idea of self mocking is this though:

You make a "test" verzion of your class, which extends your class. And then stup out the functions you want for the test.

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

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

then your test code would use that class for a stubbed version of the object.

Caleb
  • 1,088
  • 7
  • 7