我一直在查看 Moq 文档,评论太短,我无法理解它可以做的每一件事。
我没有得到的第一件事是 It.IsAny<string>(). //example using string
使用它比仅仅投入一些值(value)有优势吗?我知道有人说如果你不关心值(value)就使用它,但如果你不关心值(value),你就不能只做“a”之类的吗?这看起来更像是打字。
其次,什么时候是您不关心值(value)的例子?我认为最小起订量需要值(value)来匹配东西。
我不明白 It.Is<>是为了根本还是如何使用它。我不明白这个例子以及它想表达的意思。
接下来,我不知道什么时候使用 Times (及其 AtMost 方法等)。为什么要限制某些东西的设置次数?我有一些AppConfig我需要使用两次的值。为什么我要将它限制为一次?这只会使测试失败。这是为了阻止其他人向您的代码中添加另一个吗?
我不知道如何使用 mock.SetupAllProperties();
它用什么设置属性?
我也不明白为什么有这么多不同的方法来设置属性以及它们之间的区别是什么。文档有:
SetupGet(of property)
SetupGet<TProperty>
我注意到 Moq 中的很多东西都显示 ()和 <> - 它们之间有什么区别以及它们在使用中会是什么样子?
我也不明白为什么他们有 SetupGet .你不会使用 SetupSet设置属性?
SetupSet在文档中有五种不同的使用方式。加上另一个叫做 SetupProperty .所以我不明白为什么会有这么多。
附带说明一下,我想知道 lambda 中使用的变量是否独立于其他 lambda。例如:
mock.setup(m => m.Test);
stop.setup(m => m.Test);
这样可以吗,或者变量 m 之间会不会有一些冲突? ?
最后,我是watching this video我想知道它是否显示 Visual Studio。他的 Intellisense 看起来不一样。一个灯泡为他弹出(我很高兴我的没有,因为它带回了 netbeans 的痛苦记忆),并且有从一个左大括号到右大括号等的线条。
最佳答案
当您在被测代码中传递新的引用类型时,这些会很有用。例如,如果您有一个类似于以下行的方法:
public void CreatePerson(string name, int age) {
Person person = new Person(name, age);
_personRepository.Add(person);
}
您可能想检查存储库上是否调用了 add 方法,
[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>()));
}
如果你想让这个测试更明确,你可以使用 It.Is 通过提供一个谓词,person 对象必须匹配,
[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,则测试将通过异常。
如果您有以下方法:-
public void PayPensionContribution(Person person) {
if (person.Age > 65 || person.Age < 18) return;
//Do some complex logic
_pensionService.Pay(500M);
}
您可能想要测试的一件事是,当将 65 岁以上的人传递给该方法时,不会调用 pay 方法
[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());
}
类似地,可以想象这样一种情况:您正在迭代一个集合并为集合中的每个项目调用一个方法,并且您希望确保它被调用了一定次数,而其他时候您只需不在乎。
你需要注意的是,他们反射(reflect)的是你的代码如何与 mock 交互,而不是你如何设置 mock
public static void SetAuditProperties(IAuditable auditable) {
auditable.ModifiedBy = Thread.CurrentPrincipal.Identity.Name;
}
在这种情况下,代码设置 IAuditable 实例的 ModifiedBy 属性,同时获取当前 IPrincipal 实例的 Name 属性,
[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”,我们没有设置属性本身。
看上面的测试是不是改成了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 方法中执行任何操作,除非您告诉它这样做。实际上,模拟对象看起来有点像这样
public class AuditableMock : IAuditable {
public string ModifiedBy { get { return null; } set { } }
}
要让测试通过,您必须告诉 Moq 将属性设置为具有标准属性行为。您可以通过调用 SetupProperty 来完成此操作,模拟看起来更像
public class AuditableMock : IAuditable {
public string ModifiedBy { get; set; }
}
上面的测试将通过,因为值“test”现在将针对模拟存储。在模拟复杂对象时,您可能希望对所有属性执行此操作,因此使用 SetupAllProperties 快捷方式
最后,IDE 中的灯泡是 ReSharper 插件。
关于c# - 需要帮助以更好地理解最小起订量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1073846/
当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/
我注意到像bundler这样的项目在每个specfile中执行requirespec_helper我还注意到rspec使用选项--require,它允许您在引导rspec时要求一个文件。您还可以将其添加到.rspec文件中,因此只要您运行不带参数的rspec就会添加它。使用上述方法有什么缺点可以解释为什么像bundler这样的项目选择在每个规范文件中都需要spec_helper吗? 最佳答案 我不在Bundler上工作,所以我不能直接谈论他们的做法。并非所有项目都checkin.rspec文件。原因是这个文件,通常按照当前的惯例,只
我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121
我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法
“输出”是一个序列化的OpenStruct。定义标题try(:output).try(:data).try(:title)结束什么会更好?:) 最佳答案 或者只是这样:deftitleoutput.data.titlerescuenilend 关于ruby-on-rails-更好的替代方法try(:output).try(:data).try(:name)?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.c
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您
我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。
这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Rubysyntaxquestion:Rational(a,b)andRational.new!(a,b)我正在阅读ruby镐书,我对创建有理数的语法感到困惑。Rational(3,4)*Rational(1,2)产生=>3/8为什么Rational不需要new方法(我还注意到例如我可以在没有new方法的情况下创建字符串)?