需要帮助以更好地了解起订量 [英] Need help to understand Moq better

查看:72
本文介绍了需要帮助以更好地了解起订量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在查看Moq文档,评论太短了,以至于我无法理解它可以做的每件事.

I've been looking at the Moq documentation and the comments are too short for me to understand each of things it can do.

我没有得到的第一件事是It.IsAny<string>(). //example using string

The first thing I don't get is It.IsAny<string>(). //example using string

使用此方法是否比仅输入一些值有优势?我知道人们会说如果您不关心值就使用它,但是如果您不关心值,就不能只是做一个"a"之类的事情吗?看起来好像在打字.

Is there an advantage of using this over just putting some value in? I know people say to use this if you don't care about the value, but if you don't care about the value can't you just do "a" or something? This just seems like more typing.

第二,什么时候成为您不关心该值的例子?我以为Moq需要值来匹配东西.

Secondly, when would be an example be of when you would not care about the value? I thought Moq needs the value to match up stuff.

我根本不了解It.Is<>的用途或用途.我不理解该示例及其试图显示的内容.

I don't get what It.Is<> is for at all or how to use it. I don't understand the example and what it is trying to show.

接下来,我不知道何时使用Times(及其AtMost方法和类似方法).您为什么要限制设置内容的次数?我有一些需要两次使用的AppConfig值.我为什么要限制一次呢?这只会使测试失败.这是不是要阻止其他人向您的代码中添加其他代码?

Next, I don't get when to use Times (and its AtMost methods and similar). Why would you limit the number of times something is set up? I have some AppConfig value that I need to use twice. Why would I want to limit it to, say, once? This would just make the test fail. Is this to stop other people from adding another one to your code or something?

我不知道如何使用mock.SetupAllProperties(); 它用什么来设置属性?

I don't get how to use mock.SetupAllProperties(); What does it set up the properties with?

我也不明白为什么有这么多不同的方式来设置属性以及它们之间的区别是什么.该文档具有:

I don't also get why there are so many different ways to set up a property and what their differences are. The documentation has:

SetupGet(of property)
SetupGet<TProperty>

我注意到Moq中的许多内容都显示()<>-它们之间有什么区别,以及它们在使用中的外观是什么?

I noticed that a lot of the stuff in Moq shows () and <> - what's the difference between them and what would they look like in use?

我也不知道他们为什么有SetupGet.您不使用SetupSet设置属性吗? SetupSet在文档中有五种不同的使用方式.再加上一个叫做SetupProperty的名字.所以我不明白为什么会有这么多.

I also don't get why they have SetupGet. Would you not use SetupSet to set a property? SetupSet has five different ways to use it in the documentation. Plus another one called SetupProperty. So I don't understand why there are so many.

另一方面,我想知道lambda中使用的变量是否独立于其他lambda.例如:

On a side note, I am wondering if variables used in lambdas are independent of other lambdas. E.g.:

mock.setup(m => m.Test);
stop.setup(m => m.Test);

这可以吗,或者变量m之间是否会有一些冲突?

Would this be ok or would there be some conflict between the variable m?

最后,我观看该视频,我想知道它是否显示Visual Studio.他的Intellisense看起来与众不同.一个灯泡为他突然冒出(我不高兴,因为它带回了人们对Netbeans的痛苦回忆),并且有从一个打开的大括号到关闭的大括号等的线条.

Finally, I was watching this video and I am wondering if it shows Visual Studio. His Intellisense looks different. A lightbulb pops up for him (I am happy mine does not, as it brings back painful memories of netbeans), and there are lines going from one opening brace to the closing brace and etc.

谢谢:)

推荐答案

It.IsAny/It.Is

当您在被测代码中传递新的引用类型时,这些功能将非常有用.例如,如果您有以下方法:-

It.IsAny / It.Is

These can be useful when you're passing a new reference type within the code under test. For instance if you had a method along the lines of:-

public void CreatePerson(string name, int age) {
    Person person = new Person(name, age);
    _personRepository.Add(person);
}

您可能要检查存储库上已调用add方法

You might want to check the add method has been called on the repository

[Test]
public void Create_Person_Calls_Add_On_Repository () {
    Mock<IPersonRepository> mockRepository = new Mock<IPersonRepository>();
    PersonManager manager = new PersonManager(mockRepository.Object);
    manager.CreatePerson("Bob", 12);
    mockRepository.Verify(p => p.Add(It.IsAny<Person>()));
}

如果您想使该测试更明确,则可以使用它.通过提供谓词来使person对象必须匹配

If you wanted to make this test more explicit you can use It.Is by supplying a predicate the person object must match

[Test]
public void Create_Person_Calls_Add_On_Repository () {
    Mock<IPersonRepository> mockRepository = new Mock<IPersonRepository>();
    PersonManager manager = new PersonManager(mockRepository.Object);
    manager.CreatePerson("Bob", 12);
    mockRepository.Verify(pr => pr.Add(It.Is<Person>(p => p.Age == 12)));
}

这样,如果用于调用add方法的person对象的age属性未设置为12,则测试将通过异常.

This way the test will through an exception if the person object that was used to call the add method didn't have the age property set to 12.

如果您有以下方法:-

public void PayPensionContribution(Person person) {
    if (person.Age > 65 || person.Age < 18) return;
    //Do some complex logic
    _pensionService.Pay(500M);
}

您可能要测试的一件事是,将65岁以上的人传递给pay方法时,不会调用pay方法.

One of the things that you might want to test is that the pay method does not get called when a person aged over 65 is passed into the method

[Test]
public void Someone_over_65_does_not_pay_a_pension_contribution() {
    Mock<IPensionService> mockPensionService = new Mock<IPensionService>();
    Person p = new Person("test", 66);
    PensionCalculator calc = new PensionCalculator(mockPensionService.Object);
    calc.PayPensionContribution(p);
    mockPensionService.Verify(ps => ps.Pay(It.IsAny<decimal>()), Times.Never());
}

类似地,可以想象这样的情况:您遍历一个集合并为该集合中的每个项目调用一个方法,并且您想确保已多次调用该方法,而其他时候您只是不这样做不在乎.

Similarly it's possible to imagine situations where you're iterating over a collection and calling a method for each item in the collection and you'd like to make sure that it's been called a certain amount of times, other times you simply don't care.

您需要与这些人注意的是,它们反映了您的代码如何与模拟交互,而不是您如何设置模拟

What you need to be aware of with these guys is that they reflect how your code is interacting with the mock rather than how you're setting up the mock

public static void SetAuditProperties(IAuditable auditable) {
    auditable.ModifiedBy = Thread.CurrentPrincipal.Identity.Name;
}

在这种情况下,代码将在获取IPrincipal当前实例的Name属性的同时设置IAuditable实例的ModifiedBy属性

In this case the code is setting the ModifiedBy property of the IAuditable instance while it's getting the Name property of the current instance of IPrincipal

[Test]
public void Accesses_Name_Of_Current_Principal_When_Setting_ModifiedBy() {
    Mock<IPrincipal> mockPrincipal = new Mock<IPrincipal>();
    Mock<IAuditable> mockAuditable = new Mock<IAuditable>();

    mockPrincipal.SetupGet(p => p.Identity.Name).Returns("test");

    Thread.CurrentPrincipal = mockPrincipal.Object;
    AuditManager.SetAuditProperties(mockAuditable.Object);

    mockPrincipal.VerifyGet(p => p.Identity.Name);
    mockAuditable.VerifySet(a => a.ModifiedBy = "test");
}

在这种情况下,我们将在IPrincipal的模拟上设置name属性,以便当在Identity的Name属性上调用getter时,它返回"test",而我们并未设置该属性本身.

In this case we're setting up the name property on the mock of IPrincipal so it returns "test" when the getter is called on the Name property of Identity we're not setting the property itself.

查看上面的测试,是否将其更改为读"

Looking at the test above if it was changed to read

[Test]
public void Accesses_Name_Of_Current_Principal_When_Setting_ModifiedBy() {
    Mock<IPrincipal> mockPrincipal = new Mock<IPrincipal>();
    Mock<IAuditable> mockAuditable = new Mock<IAuditable>();
    mockPrincipal.SetupGet(p => p.Identity.Name).Returns("test");

    var auditable = mockAuditable.Object;

    Thread.CurrentPrincipal = mockPrincipal.Object;
    AuditManager.SetAuditProperties(auditable);

    Assert.AreEqual("test", auditable.ModifiedBy);
}

测试将失败.这是因为Moq创建的代理实际上不会在属性的set方法中执行任何操作,除非您告知它.在影响模拟对象看起来像这样

The test would fail. This is because the proxy created by Moq doesn't actually do anything in the set method of a property unless you tell it to. In affect the mock object looks a bit like this

public class AuditableMock : IAuditable {
     public string ModifiedBy { get { return null; } set { } }

} 

要使测试通过,您必须告诉Moq将属性设置为具有标准属性行为.您可以通过调用SetupProperty来执行此操作,该模拟看起来更像

To get the test to pass you have to tell Moq to setup the property to have the standard property behaviour. You can do this by calling SetupProperty and the mock will look more like

public class AuditableMock : IAuditable {
     public string ModifiedBy { get; set; }
} 

,上面的测试将通过,因为现在将值"test"存储在该模拟中.在模拟复杂对象时,您可能需要对所有属性执行此操作,因此需要使用SetupAllProperties快捷方式

and the test above would pass as the value "test" would now get stored against the mock. When mocking complex objects you might want to do this for all properties, hence the SetupAllProperties shortcut

最后,IDE中的灯泡是resharper插件.

Finally, the lightbulb in the IDE is the resharper plugin.

这篇关于需要帮助以更好地了解起订量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆