无法理解最小起订量
Trouble understanding Moq
我无法掌握 Moq 框架。他们从最小起订量网站给出了这个例子...
// Assumptions:
public interface IFoo {
public bool DoSomething(string);
public bool TryParse(string, out string));
}
var mock = new Mock<IFoo>();
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);
Moq 设置在这里做什么?
// out arguments
var outString = "ack";
// TryParse will return true, and the out argument will return "ack", lazy evaluated
mock.Setup(foo => foo.TryParse("ping", out outString)).Returns(true);
同样的问题..正在设置什么?
有谁知道可能更深入的最小起订量指南?我读了这本 SO post where the book The Art of Unit Testing with Examples in .NET 推荐,但是这本书很旧,已经绝版了。
对于模拟的一般背景,this answer 很好地解释了它以及为什么您可能想在单元测试中使用它。
具体来说,Moq 是一个允许您轻松创建模拟对象并控制其行为的库。用例子描述是最简单的,所以让我们看看你的第一个代码示例:
public interface IFoo {
public bool DoSomething(string);
public bool TryParse(string, out string));
}
/* 1 */ var mock = new Mock<IFoo>();
/* 2 */ mock.Setup(foo => foo.DoSomething("ping")).Returns(true);
第 1 行创建 IFoo
接口的 模拟实现 。在幕后,Moq 正在使用 Castle DynamicProxy 库动态创建 IFoo
的具体实现,然后将其包装在自己的 Mock
class 中,以便我们可以配置它的行为。
现在我们有了一个模拟对象,我们将经常需要配置它如何响应调用其方法。这样,我们就可以测试我们的被测系统将如何对其做出反应。第 2 行的 Setup
方法正是这样做的,它告诉我们的模拟对象 return true
当使用等于 "ping"
的参数调用 DoSomething
时。假设您正在使用此模拟来测试 class,如下所示:
public class TestObject
{
public string TestMethod(IFoo foo)
{
if (foo.DoSomething("ping"))
return "ping";
else if (foo.DoSomething("pong"))
return "pong";
return "blah";
}
}
要获得完整的测试覆盖率,您需要 IFoo
的实现可以:
- return
true
一次测试 "ping"
- return
true
在另一个测试中 "pong"
- return
false
对于上次测试中的任何参数
您可以创建您自己的具有此行为的模拟对象,例如:
public class MockFoo : IFoo
{
string trueValue;
public MockFoo(string trueValue)
{
this.trueValue = trueValue;
}
public bool DoSomething(string value)
{
return value == trueValue;
}
}
但是当您有复杂的逻辑、多个参数或许多依赖项时,这会很痛苦;它只是不能很好地扩展。这就是模拟对象和 Moq 可以使事情变得简单的地方。三个测试在最小起订量中的相同设置是:
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);
mock.Setup(foo => foo.DoSomething("pong")).Returns(true);
mock.Setup(foo => foo.DoSomething(It.IsAny<string>())).Returns(false);
在我看来,这更简单也更能表达您对 IFoo
依赖行为的期望。
至于指南,我认为您最好使用一般模拟指南而不是 Moq-specific 指南。 Moq 只是一个使模拟对象的使用更容易的库,Quickstart is a pretty good reference for the mechanics of using Moq. There are dozens of mocking tutorials and guides, just look for some. And remember, it didn't really "click" for me until I started using them. Find a coding kata 并尝试自己模拟!
我无法掌握 Moq 框架。他们从最小起订量网站给出了这个例子...
// Assumptions:
public interface IFoo {
public bool DoSomething(string);
public bool TryParse(string, out string));
}
var mock = new Mock<IFoo>();
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);
Moq 设置在这里做什么?
// out arguments
var outString = "ack";
// TryParse will return true, and the out argument will return "ack", lazy evaluated
mock.Setup(foo => foo.TryParse("ping", out outString)).Returns(true);
同样的问题..正在设置什么?
有谁知道可能更深入的最小起订量指南?我读了这本 SO post where the book The Art of Unit Testing with Examples in .NET 推荐,但是这本书很旧,已经绝版了。
对于模拟的一般背景,this answer 很好地解释了它以及为什么您可能想在单元测试中使用它。
具体来说,Moq 是一个允许您轻松创建模拟对象并控制其行为的库。用例子描述是最简单的,所以让我们看看你的第一个代码示例:
public interface IFoo {
public bool DoSomething(string);
public bool TryParse(string, out string));
}
/* 1 */ var mock = new Mock<IFoo>();
/* 2 */ mock.Setup(foo => foo.DoSomething("ping")).Returns(true);
第 1 行创建 IFoo
接口的 模拟实现 。在幕后,Moq 正在使用 Castle DynamicProxy 库动态创建 IFoo
的具体实现,然后将其包装在自己的 Mock
class 中,以便我们可以配置它的行为。
现在我们有了一个模拟对象,我们将经常需要配置它如何响应调用其方法。这样,我们就可以测试我们的被测系统将如何对其做出反应。第 2 行的 Setup
方法正是这样做的,它告诉我们的模拟对象 return true
当使用等于 "ping"
的参数调用 DoSomething
时。假设您正在使用此模拟来测试 class,如下所示:
public class TestObject
{
public string TestMethod(IFoo foo)
{
if (foo.DoSomething("ping"))
return "ping";
else if (foo.DoSomething("pong"))
return "pong";
return "blah";
}
}
要获得完整的测试覆盖率,您需要 IFoo
的实现可以:
- return
true
一次测试"ping"
- return
true
在另一个测试中"pong"
- return
false
对于上次测试中的任何参数
您可以创建您自己的具有此行为的模拟对象,例如:
public class MockFoo : IFoo
{
string trueValue;
public MockFoo(string trueValue)
{
this.trueValue = trueValue;
}
public bool DoSomething(string value)
{
return value == trueValue;
}
}
但是当您有复杂的逻辑、多个参数或许多依赖项时,这会很痛苦;它只是不能很好地扩展。这就是模拟对象和 Moq 可以使事情变得简单的地方。三个测试在最小起订量中的相同设置是:
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);
mock.Setup(foo => foo.DoSomething("pong")).Returns(true);
mock.Setup(foo => foo.DoSomething(It.IsAny<string>())).Returns(false);
在我看来,这更简单也更能表达您对 IFoo
依赖行为的期望。
至于指南,我认为您最好使用一般模拟指南而不是 Moq-specific 指南。 Moq 只是一个使模拟对象的使用更容易的库,Quickstart is a pretty good reference for the mechanics of using Moq. There are dozens of mocking tutorials and guides, just look for some. And remember, it didn't really "click" for me until I started using them. Find a coding kata 并尝试自己模拟!