Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing a method with Moq

I'm trying to learn how to do Unit testing with C# and Moq, and I've built a little test situation. Given this code:

public interface IUser
{

    int CalculateAge();
    DateTime DateOfBirth { get; set; }
    string Name { get; set; }
}

public class User : IUser
{
    public DateTime DateOfBirth { get; set; }
    string Name { get; set; }

    public int CalculateAge()
    {
        return DateTime.Now.Year - DateOfBirth.Year;
    }
}

I want to test the method CalculateAge(). To do this, I thought I should try giving a default value to the DateOfBirth property by doing this in my test method:

var userMock = new Mock<IUser>();
userMock.SetupProperty(u => u.DateOfBirth, new DateTime(1990, 3, 25)); //Is this supposed to give a default value for the property DateOfBirth ?
Assert.AreEqual(22, userMock.Object.CalculateAge());

But when It comes to the assertion, the value of CalculateAge() equals 0, although DateOfBirth equals new DateTime(1990, 3, 25).

I know this may look like a silly example, but whatever... I thought I could use mocking to give values to not-yet-developed method/properties in my objects, so the testing of a method wouldn't depend on another component of my class, or even setting up a default context for my object (hence the name of the user here...) Am I approaching this problem the wrong way?

Thanks.

like image 988
Pacane Avatar asked May 25 '12 19:05

Pacane


People also ask

Why do we use Moq in unit testing?

Moq is a mocking framework built to facilitate the testing of components with dependencies. As shown earlier, dealing with dependencies could be cumbersome because it requires the creation of test doubles like fakes. Moq makes the creation of fakes redundant by using dynamically generated types.

Can we mock static methods using Moq?

You can use Moq to mock non-static methods but it cannot be used to mock static methods.

Is Moq a testing framework?

The Moq framework is an open source unit testing framework that works very well with . NET code and Phil shows us how to use it.


2 Answers

Yes, you approaching it wrong, but don't worry, I'll explain why. First hint would be

you can completely remove your User class and everything will be the same.

When you are doing:

var userMock = new Mock<IUser>();

You just creating a fake\mock object of that interface, that has nothing to do with your initial User class, so it doesn't have any implementation of CalculateAge method, except of fake one that just silly returns 0. That's why you are getting 0 in your assert statement.

So, you were saying:

thought I could use mocking to give values to not-yet-developed method/properties in my objects, so the testing of a method wouldn't depend on another component of my class

You could, let's say you will have some consumer of your IUser, lets say like the following:

class ConsumerOfIUser
{
   public int Consume(IUser user)
   {
      return user.CalculateAge() + 10;
   }
}

in that case mocking of IUser will make total sense, since you want to test how your ConsumerOfIUser behaves when IUser.CalculateAge() returns 10. You would do the following:

var userMock = new Mock<IUser>();
userMock.Setup(u => u.CalculateAge()).Returns(10);

var consumer = new ConsumerOfIUser();
var result = consumer.Consume(userMock);

Assert.AreEqual(result, 20); //should be true
like image 134
Restuta Avatar answered Oct 06 '22 08:10

Restuta


It depends on what your trying to test. In this case, you have mocked out the User object, so there is no point in testing anything inside this class as you are replacing it with a mock object. If you want to test the User object then you shouldn't mock it out.

Mocks are used to replace dependant objects that you don't want to test. For example, if you had a Name object instead of a string (e.g contains first name, surname, title etc..) but you didn't want to test the Name object, just the User object, you would create a mock of the Name object to be used when constructing the User object.

like image 28
Ben Avatar answered Oct 06 '22 10:10

Ben