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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10760153/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 15:08:58  来源:igfitidea点击:

Unit testing a method with Moq

c#unit-testingmoq

提问by Pacane

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:

我正在尝试学习如何使用 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;
    }
}

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

我想测试这个方法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());

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

但是当谈到断言时, 的值CalculateAge()等于 0,虽然DateOfBirth等于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.

谢谢。

采纳答案by Restuta

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

是的,你的方法是错误的,但别担心,我会解释原因。第一个提示是

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

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

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 Userclass, so it doesn't have any implementation of CalculateAgemethod, except of fake one that just silly returns 0. That's why you are getting 0 in your assert statement.

您只是创建了该接口的假\模拟对象,这与您的初始User类无关,因此它没有任何CalculateAge方法的实现,除了假的只是愚蠢地返回 0 之外。这就是为什么您在其中获得 0你的断言声明。

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:

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

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 ConsumerOfIUserbehaves when IUser.CalculateAge() returns 10. You would do the following:

在这种情况下,模拟 IUser 将完全有意义,因为您想测试ConsumerOfIUser当 IUser.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

回答by Ben

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.

这取决于您尝试测试的内容。在这种情况下,您已经模拟了 User 对象,因此当您将其替换为模拟对象时,没有必要测试此类中的任何内容。如果你想测试 User 对象,那么你不应该模拟它。

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.

模拟用于替换您不想测试的依赖对象。例如,如果您有一个 Name 对象而不是一个字符串(例如包含名字、姓氏、标题等),但您不想测试 Name 对象,只是 User 对象,您将创建一个模拟构造用户对象时要使用的名称对象。