使用Moq对方法进行单元测试

Pac*_*ane 18 c# unit-testing moq

我正在尝试学习如何使用C#和Moq进行单元测试,并且我已经构建了一个小测试情况.鉴于此代码:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我想测试一下这个方法CalculateAge().为此,我想我应该尝试DateOfBirth通过在我的测试方法中执行此操作来为属性提供默认值:

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());
Run Code Online (Sandbox Code Playgroud)

但是当谈到断言时,CalculateAge()等于0 的值虽然DateOfBirth等于new DateTime(1990, 3, 25).

我知道这可能看起来像一个愚蠢的例子,但无论如何......我想我可以使用模拟为我的对象中尚未开发的方法/属性赋值,因此方法的测试不依赖于另一个组件我的班级,甚至为我的对象设置默认上下文(因此这里的用户名称......)我是否以错误的方式处理这个问题?

谢谢.

Res*_*uta 23

是的,你接近错了,但不要担心,我会解释原因.第一个提示是

你可以完全删除你的User课程,一切都会一样.

当你这样做时:

var userMock = new Mock<IUser>();
Run Code Online (Sandbox Code Playgroud)

你只是创建了一个与该初始User类无关的该接口的假\模拟对象,所以它没有任何CalculateAge方法的实现,除了假的只是愚蠢的返回0.这就是你得到0的原因你的断言陈述.

所以,你说:

以为我可以使用mocking为我的对象中尚未开发的方法/属性赋值,因此方法的测试不依赖于我的类的另一个组件

你可以,假设你有一些IUser的消费者,让我们说如下:

class ConsumerOfIUser
{
   public int Consume(IUser user)
   {
      return user.CalculateAge() + 10;
   }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,IUser的模拟将完全有意义,因为您想测试ConsumerOfIUserIUser.CalculateAge()返回10时的行为.您将执行以下操作:

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
Run Code Online (Sandbox Code Playgroud)

  • @Pacane,没错.测试没有外部依赖关系的类(最纯粹的形式)不应该需要mock或stub. (4认同)
  • 下载东西的方法应该写在另一个类中,可以模拟出来进行测试. (3认同)