有没有办法复制 Moq Mock<>按价值?

发布于 2024-08-02 09:13:32 字数 339 浏览 1 评论 0 原文

我在 System.Data.DataSet 前面使用接口(IDataSet)用于测试目的。我希望能够模拟 Copy() 方法。基本上我想要同一个模拟对象的副本/克隆。

这是我想做的一些伪代码。

Mock<IDataSet> dataMock = new Mock<IDataSet>();
Mock<IDataSet> copyMock = ???    // How do I clone the mock?

dataMock.Setup(c => c.Copy()).Returns(copyMock.Object);

这可能吗?

I am using an interface (IDataSet) in front of System.Data.DataSet for testing purposes. I want to be able to mock the Copy() method. Basically I want a copy/clone of the same mocked object.

Here's some pseudo code of what I would like to do.

Mock<IDataSet> dataMock = new Mock<IDataSet>();
Mock<IDataSet> copyMock = ???    // How do I clone the mock?

dataMock.Setup(c => c.Copy()).Returns(copyMock.Object);

Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

策马西风 2024-08-09 09:13:32

基本上,Mock 不是真实的东西,因此它没有真正的行为。它不应该有真正的行为——它应该做你告诉它的任何事情,同时跟踪发生的事情。不多也不少。

这意味着必须告诉它其 Copy 方法如何工作。如果您执行以下操作,就是 Copy 方法将具有的实现:

Mock<IDataSet> dataMock = new Mock<IDataSet>();
Mock<IDataSet> copyMock = new Mock<IDataSet>();

dataMock.Setup(c => c.Copy()).Returns(copyMock.Object);

但是,您也可以执行以下操作:

Mock<IDataSet> dataMock = new Mock<IDataSet>();
Mock<IDataSet> copyMock = dataMock;

dataMock.Setup(c => c.Copy()).Returns(copyMock.Object);

然后,that 就成为 Copy 方法的实现。请记住:接口不是一个规定方法应该做什么的契约;而是一个契约。它仅定义方法的签名。

您可能希望将数据从一个 IDataSet 复制到另一个 IDataSet,但请记住 Mock 是纯粹的行为;它没有数据。

您可以考虑以下几种替代方案:

  • 将 IDataSet 替换为抽象 DataSetBase 类,并按照您希望的方式实现 Copy 方法(也就是说,不是作为抽象或虚拟方法) 。
  • 不要创建 IDataSet 的 Mock,而是使用 Fake。 Fake 是接口的特定于测试的实现,其行为接近真实的接口。没有用于创建 Fake 的框架/库,因此您需要手动编写这样的 Fake 代码。
  • 考虑 Copy 方法是否真的应该成为接口的一部分。在我看来,这是一个首先不属于接口的实现细节。

您可以在优秀书籍 xUnit 中阅读有关 Stubs、Mocks、Fakes 和其他单元测试设计模式的内容测试模式

Basically, a Mock is not the real thing, so it does not have real behavior. It's not supposed to have real behavior - it's supposed to do whatever you tell it while keeping track of what happened. Nothing more and nothing less.

This means that you have to tell it how its Copy method works. If you do the following, that's the implmementation the Copy method will have:

Mock<IDataSet> dataMock = new Mock<IDataSet>();
Mock<IDataSet> copyMock = new Mock<IDataSet>();

dataMock.Setup(c => c.Copy()).Returns(copyMock.Object);

However, you can also do this:

Mock<IDataSet> dataMock = new Mock<IDataSet>();
Mock<IDataSet> copyMock = dataMock;

dataMock.Setup(c => c.Copy()).Returns(copyMock.Object);

and that, then, becomes the implementation of the Copy method. Remember: an interface is not a contract that states what the method should do; it only defines the signature of methods.

You were probably hoping to copy data from one IDataSet to another, but remember that a Mock is pure behavior; it has no data.

A couple of alternatives you can think about are the following:

  • Replace IDataSet with an abstract DataSetBase class, and implement the Copy method like you want it to behave (that is, not as an abstract or virtual method).
  • Instead of creating a Mock of IDataSet, use a Fake. A Fake is a a test-specifict implementation of an interface that has behavior close to the real thing. There are no frameworks/libraries for creating Fakes, so you would need to code such a Fake by hand.
  • Consider whether the Copy method should really be part of the interface. It sounds to me like it's an implementation detail that doesn't belong on the interface in the first place.

You can read about Stubs, Mocks, Fakes and other unit testing design patterns in the excellent book xUnit Test Patterns.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文