如何模拟结构的多个实例?
How can I mock multiple instances of a struct?
我有一个 struct
我想模拟。在更复杂的测试中,我需要这个结构的多个实例,每个实例都有自己的行为。为此,我创建了一个辅助方法。
private MyStruct CreateMock(string toString) {
var mock = Mock.Create<MyStruct>();
Mock.Arrange(() => mock.toString()).Returns(toString);
return mock;
}
当我调试多次调用此方法的测试时,似乎 Arrange
调用被结构的所有实例覆盖(或者也许我正在使用结构模拟而不是实例模拟? ).
我试过:
mock.Arrange(m => m.toString()).Returns(toString); // Using Helpers assembly, note the lowercase m at the start of the line.
但无济于事。如何获取结构的多个实例?
我正在使用:
微软 Visual Studio 企业版 2017
版本 15.9.17
VisualStudio.15.Release/15.9.17+28307.905
微软.NET框架
版本 4.8.03761
已安装版本:Enterprise
JustMock 2020.1.219.1
Telerik JustMock 扩展。
示例已添加:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Telerik.JustMock;
using Telerik.JustMock.Helpers;
namespace JustMockFramework
{
public struct MyStruct
{
public readonly string Id;
public MyStruct(string id)
{
Id = id;
}
public new string ToString()
{
return "Never read me!";
}
}
[TestClass]
public class MWE
{
[TestMethod]
public void TestSimpleStruct()
{
var simpleTest = new MyStruct("1");
Assert.AreEqual("Never read me!", simpleTest.ToString());
}
[TestMethod]
public void TestMockOfStruct()
{
var mock = Mock.Create<MyStruct>();
Mock.Arrange(() => mock.ToString()).Returns("Read me!");
Assert.AreEqual("Read me!", mock.ToString());
}
[TestMethod]
public void TestTwoMocksOfStruct()
{
var firstMock = Mock.Create<MyStruct>();
Mock.Arrange(() => firstMock.ToString()).Returns("Read me!");
var secondMock = Mock.Create<MyStruct>();
Mock.Arrange(() => secondMock.ToString()).Returns("Read me too!");
Assert.AreEqual("Read me!", firstMock.ToString()); // Fails with "Read me too!"
Assert.AreEqual("Read me too!", secondMock.ToString());
}
[TestMethod]
public void TestTwoMocksOfStructCreatedInHelper()
{
var firstMock = CreateMockOfStruct("Read me!");
var secondMock = CreateMockOfStruct("Read me too!");
Assert.AreEqual("Read me!", firstMock.ToString()); // Fails with "Read me too!"
Assert.AreEqual("Read me too!", secondMock.ToString());
}
private MyStruct CreateMockOfStruct(string toString)
{
var mock = Mock.Create<MyStruct>();
Mock.Arrange(() => mock.ToString()).Returns(toString);
return mock;
}
[TestMethod]
public void TestTwoMocksOfStructCreatedInHelperWithHelper()
{
var firstMock = CreateMockOfStructWithHelper("Read me!");
var secondMock = CreateMockOfStructWithHelper("Read me too!");
Assert.AreEqual("Read me!", firstMock.ToString()); // Fails with "Read me too!"
Assert.AreEqual("Read me too!", secondMock.ToString());
}
private MyStruct CreateMockOfStructWithHelper(string toString)
{
var mock = Mock.Create<MyStruct>();
mock.Arrange((m) => m.ToString()).Returns(toString);
return mock;
}
}
}
编辑:交叉发布
我已经在 the Telerik JustMock forum
上交叉发布了这个问题
编辑:许可证扩展
我的试用许可得到了慷慨的延期。我已经更新了答案以反映这一点。
使用InSequence()
例如:
var firstMock = Mock.Create<MyStruct>();
Mock.Arrange(() => firstMock.ToString()).Returns("Read me!").InSequence();
var secondMock = Mock.Create<MyStruct>();
Mock.Arrange(() => secondMock.ToString()).Returns("Read me too!").InSequence();
您需要为这些类型的场景使用Autofixture。
https://github.com/AutoFixture/AutoFixture.
正如问题中所述,我交叉发布了问题并在那里得到了答案。
这一切都归结为价值与参考的比较。我假设是参考比较,但使用了值比较。当实际将 id
传递给模拟的创建时,它应该可以工作。
为方便起见,一份 Telerik 提出的解决方案的副本。
public struct MyStruct
{
public readonly string Id;
public MyStruct(string id)
{
Id = id;
}
public override string ToString()
{
return "Never read me!";
}
}
[TestClass]
public class MWE
{
[TestMethod]
public void TestSimpleStruct()
{
var simpleTest = new MyStruct("1");
Assert.AreEqual("Never read me!", simpleTest.ToString());
}
[TestMethod]
public void TestMockOfStruct()
{
var mock = Mock.Create<MyStruct>("1");
Mock.Arrange(() => mock.ToString()).Returns("Read me!");
Assert.AreEqual("Read me!", mock.ToString());
}
[TestMethod]
public void TestTwoMocksOfStruct()
{
var firstMock = Mock.Create<MyStruct>("1");
Mock.Arrange(() => firstMock.ToString()).Returns("Read me!");
var secondMock = Mock.Create<MyStruct>("2");
Mock.Arrange(() => secondMock.ToString()).Returns("Read me too!");
Assert.AreEqual("Read me!", firstMock.ToString()); // Fails with "Read me too!"
Assert.AreEqual("Read me too!", secondMock.ToString());
}
[TestMethod]
public void TestTwoMocksOfStructCreatedInHelper()
{
var firstMock = CreateMockOfStruct("1", "Read me!");
var secondMock = CreateMockOfStruct("2", "Read me too!");
Assert.AreEqual("Read me!", firstMock.ToString()); // Fails with "Read me too!"
Assert.AreEqual("Read me too!", secondMock.ToString());
}
private MyStruct CreateMockOfStruct(string id, string toString)
{
var mock = Mock.Create<MyStruct>(id);
Mock.Arrange(() => mock.ToString()).Returns(toString);
return mock;
}
[TestMethod]
public void TestTwoMocksOfStructCreatedInHelperWithHelper()
{
var firstMock = CreateMockOfStructWithHelper("1", "Read me!");
var secondMock = CreateMockOfStructWithHelper("2", "Read me too!");
Assert.AreEqual("Read me!", firstMock.ToString()); // Fails with "Read me too!"
Assert.AreEqual("Read me too!", secondMock.ToString());
}
private MyStruct CreateMockOfStructWithHelper(string id, string toString)
{
var mock = Mock.Create<MyStruct>(id);
mock.Arrange((m) => m.ToString()).Returns(toString);
return mock;
}
}
我有一个 struct
我想模拟。在更复杂的测试中,我需要这个结构的多个实例,每个实例都有自己的行为。为此,我创建了一个辅助方法。
private MyStruct CreateMock(string toString) {
var mock = Mock.Create<MyStruct>();
Mock.Arrange(() => mock.toString()).Returns(toString);
return mock;
}
当我调试多次调用此方法的测试时,似乎 Arrange
调用被结构的所有实例覆盖(或者也许我正在使用结构模拟而不是实例模拟? ).
我试过:
mock.Arrange(m => m.toString()).Returns(toString); // Using Helpers assembly, note the lowercase m at the start of the line.
但无济于事。如何获取结构的多个实例?
我正在使用: 微软 Visual Studio 企业版 2017 版本 15.9.17 VisualStudio.15.Release/15.9.17+28307.905 微软.NET框架 版本 4.8.03761
已安装版本:Enterprise
JustMock 2020.1.219.1 Telerik JustMock 扩展。
示例已添加:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Telerik.JustMock;
using Telerik.JustMock.Helpers;
namespace JustMockFramework
{
public struct MyStruct
{
public readonly string Id;
public MyStruct(string id)
{
Id = id;
}
public new string ToString()
{
return "Never read me!";
}
}
[TestClass]
public class MWE
{
[TestMethod]
public void TestSimpleStruct()
{
var simpleTest = new MyStruct("1");
Assert.AreEqual("Never read me!", simpleTest.ToString());
}
[TestMethod]
public void TestMockOfStruct()
{
var mock = Mock.Create<MyStruct>();
Mock.Arrange(() => mock.ToString()).Returns("Read me!");
Assert.AreEqual("Read me!", mock.ToString());
}
[TestMethod]
public void TestTwoMocksOfStruct()
{
var firstMock = Mock.Create<MyStruct>();
Mock.Arrange(() => firstMock.ToString()).Returns("Read me!");
var secondMock = Mock.Create<MyStruct>();
Mock.Arrange(() => secondMock.ToString()).Returns("Read me too!");
Assert.AreEqual("Read me!", firstMock.ToString()); // Fails with "Read me too!"
Assert.AreEqual("Read me too!", secondMock.ToString());
}
[TestMethod]
public void TestTwoMocksOfStructCreatedInHelper()
{
var firstMock = CreateMockOfStruct("Read me!");
var secondMock = CreateMockOfStruct("Read me too!");
Assert.AreEqual("Read me!", firstMock.ToString()); // Fails with "Read me too!"
Assert.AreEqual("Read me too!", secondMock.ToString());
}
private MyStruct CreateMockOfStruct(string toString)
{
var mock = Mock.Create<MyStruct>();
Mock.Arrange(() => mock.ToString()).Returns(toString);
return mock;
}
[TestMethod]
public void TestTwoMocksOfStructCreatedInHelperWithHelper()
{
var firstMock = CreateMockOfStructWithHelper("Read me!");
var secondMock = CreateMockOfStructWithHelper("Read me too!");
Assert.AreEqual("Read me!", firstMock.ToString()); // Fails with "Read me too!"
Assert.AreEqual("Read me too!", secondMock.ToString());
}
private MyStruct CreateMockOfStructWithHelper(string toString)
{
var mock = Mock.Create<MyStruct>();
mock.Arrange((m) => m.ToString()).Returns(toString);
return mock;
}
}
}
编辑:交叉发布
我已经在 the Telerik JustMock forum
上交叉发布了这个问题编辑:许可证扩展
我的试用许可得到了慷慨的延期。我已经更新了答案以反映这一点。
使用InSequence()
例如:
var firstMock = Mock.Create<MyStruct>();
Mock.Arrange(() => firstMock.ToString()).Returns("Read me!").InSequence();
var secondMock = Mock.Create<MyStruct>();
Mock.Arrange(() => secondMock.ToString()).Returns("Read me too!").InSequence();
您需要为这些类型的场景使用Autofixture。 https://github.com/AutoFixture/AutoFixture.
正如问题中所述,我交叉发布了问题并在那里得到了答案。
这一切都归结为价值与参考的比较。我假设是参考比较,但使用了值比较。当实际将 id
传递给模拟的创建时,它应该可以工作。
为方便起见,一份 Telerik 提出的解决方案的副本。
public struct MyStruct
{
public readonly string Id;
public MyStruct(string id)
{
Id = id;
}
public override string ToString()
{
return "Never read me!";
}
}
[TestClass]
public class MWE
{
[TestMethod]
public void TestSimpleStruct()
{
var simpleTest = new MyStruct("1");
Assert.AreEqual("Never read me!", simpleTest.ToString());
}
[TestMethod]
public void TestMockOfStruct()
{
var mock = Mock.Create<MyStruct>("1");
Mock.Arrange(() => mock.ToString()).Returns("Read me!");
Assert.AreEqual("Read me!", mock.ToString());
}
[TestMethod]
public void TestTwoMocksOfStruct()
{
var firstMock = Mock.Create<MyStruct>("1");
Mock.Arrange(() => firstMock.ToString()).Returns("Read me!");
var secondMock = Mock.Create<MyStruct>("2");
Mock.Arrange(() => secondMock.ToString()).Returns("Read me too!");
Assert.AreEqual("Read me!", firstMock.ToString()); // Fails with "Read me too!"
Assert.AreEqual("Read me too!", secondMock.ToString());
}
[TestMethod]
public void TestTwoMocksOfStructCreatedInHelper()
{
var firstMock = CreateMockOfStruct("1", "Read me!");
var secondMock = CreateMockOfStruct("2", "Read me too!");
Assert.AreEqual("Read me!", firstMock.ToString()); // Fails with "Read me too!"
Assert.AreEqual("Read me too!", secondMock.ToString());
}
private MyStruct CreateMockOfStruct(string id, string toString)
{
var mock = Mock.Create<MyStruct>(id);
Mock.Arrange(() => mock.ToString()).Returns(toString);
return mock;
}
[TestMethod]
public void TestTwoMocksOfStructCreatedInHelperWithHelper()
{
var firstMock = CreateMockOfStructWithHelper("1", "Read me!");
var secondMock = CreateMockOfStructWithHelper("2", "Read me too!");
Assert.AreEqual("Read me!", firstMock.ToString()); // Fails with "Read me too!"
Assert.AreEqual("Read me too!", secondMock.ToString());
}
private MyStruct CreateMockOfStructWithHelper(string id, string toString)
{
var mock = Mock.Create<MyStruct>(id);
mock.Arrange((m) => m.ToString()).Returns(toString);
return mock;
}
}