在等待我的 VS 2010 许可证时,我目前正在从外部检查 Moles,我想知道 Moles 是否允许我:
- 提供为一个被mole的方法分配多个mole代表的能力,也许是在测试夹具设置级别?
- 在我的测试用例中在运行时切换,对于即将被隔离的 moled 方法的调用,必须调用我的哪些 moole 代表?
有什么提示吗?
在等待我的 VS 2010 许可证时,我目前正在从外部检查 Moles,我想知道 Moles 是否允许我:
有什么提示吗?
在 detour 方法中包含门控逻辑比在同一方法中使用两个存根要容易得多,也更有意义!例如,MyMethod从磁盘上的三个不同文件中读取数据,每个文件都需要返回不同的模拟数据。我们可以绕过System.IO.File.OpenRead并通过分析OpenRead的输入参数来门控返回值:
测试方法:
[TestMethod]
[HostType("Moles")]
public void Test()
{
System.IO.Moles.MFile.OpenReadString = filePath => {
var mockStream = new System.IO.FileStream();
byte[] buffer;
switch (filePath)
{
case @"C:\DataFile.dat":
mockStream.Write(buffer, 0, 0); // Populate stream
break;
case @"C:\TextFile.txt":
mockStream.Write(buffer, 0, 0); // Populate stream
break;
case @"C:\LogFile.log":
mockStream.Write(buffer, 0, 0); // Populate stream
break;
}
return mockStream;
};
var target = new MyClass();
target.MyMethod();
}
目标类型:
using System.IO;
public class MyClass
{
public void MyMethod()
{
var fileAData = File.OpenRead(@"C:\DataFile.dat");
var fileBData = File.OpenRead(@"C:\TextFile.txt");
var fileCData = File.OpenRead(@"C:\LogFile.log");
}
}
是 #1:为每个绕行实例化一种类型,然后将每种类型用于所需的行为。并且,对#2 是的:对鼹鼠类型的一个实例或另一个实例采取行动。这需要添加方法输入参数或类构造函数注入。
例如,MyMethod从磁盘读取三个数据文件,您需要传回三个不同的数据模拟。 MyMethod需要三个参数,这是一个明显侵入性的解决方案。(注意输入参数为 FileInfo 类型;因为 System.IO>File 是静态的,不能实例化:例如:
测试方法:
[TestMethod]
[HostType("Moles")]
public void Test()
{
var fileInfoMoleA = new System.IO.Moles.MFileInfo();
fileInfoMoleA.OpenRead = () => { return new FileStream(); };
var fileInfoMoleB = new System.IO.Moles.MFileInfo();
fileInfoMoleB.OpenRead = () => { return new FileStream(); };
var fileInfoMoleC = new System.IO.Moles.MFileInfo();
fileInfoMoleC.OpenRead = () => { return new FileStream(); };
var target = new MyClass();
target.MyMethod(fileInfoMoleA, fileInfoMoleB, fileInfoMoleC);
}
目标类型:
using System.IO;
public class MyClass
{
// Input parameters are FileInfo type; because, System.IO.File
// is a static class, and can not be instantiated.
public void MyMethod(FileInfo fileInfoA, FileInfo fileInfoB, FileInfo fileInfoC)
{
var fileAData = fileInfoA.OpenRead();
var fileBData = fileInfoB.OpenRead();
var fileCData = fileInfoC.OpenRead();
}
}
作为对@Chai 评论的回应,可以在测试项目中创建通用方法,这些方法可以被引用为mole detour 委托。例如,您可能希望编写一个可以被任何单元测试引用的通用方法,它设置了各种预配置的场景。以下示例显示了如何使用参数化方法。发挥创意——它们只是方法调用!
目标类型:
namespace PexMoleDemo
{
public class MyClass
{
private MyMath _math;
public MyClass()
{
_math = new MyMath() { left = 1m, right = 2m };
}
public decimal GetResults()
{
return _math.Divide();
}
}
public class MyOtherClass
{
private MyMath _math;
public MyOtherClass()
{
_math = new MyMath() { left = 100m, right = 200m };
}
public decimal Divide()
{
return _math.Divide();
}
}
public class MyMath
{
public decimal left { get; set; }
public decimal right { get; set; }
public decimal Divide()
{
return left / right;
}
}
}
测试方法: ArrangeScenarios() 通过打开枚举参数设置摩尔绕道。这允许在许多测试中以 DRY 方式建立相同的场景。
using System;
using Microsoft.Moles.Framework;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PexMoleDemo;
[assembly: MoledAssembly("PexMoleDemo")]
namespace TestProject1
{
[TestClass()]
public class ProgramTest
{
public enum Scenarios
{
DivideByZero,
MultiplyInsteadOfDivide
}
private void ArrangeScenario(Scenarios scenario)
{
switch (scenario)
{
case Scenarios.DivideByZero:
PexMoleDemo.Moles.MMyMath.AllInstances.rightGet =
instance => { return 0m; };
break;
case Scenarios.MultiplyInsteadOfDivide:
PexMoleDemo.Moles.MMyMath.AllInstances.Divide =
instance => { return instance.left * instance.right; };
break;
default:
throw new NotImplementedException("Invalid scenario.");
}
}
[TestMethod]
[HostType("Moles")]
[ExpectedException(typeof(DivideByZeroException))]
public void Test1()
{
ArrangeScenario(Scenarios.DivideByZero);
var target = new PexMoleDemo.MyClass();
var math = new PexMoleDemo.MyMath() { left = 1, right = 2 };
var left = math.left;
var right = math.right;
var actual = target.GetResults();
}
[TestMethod]
[HostType("Moles")]
public void Test2()
{
ArrangeScenario(Scenarios.MultiplyInsteadOfDivide);
// Perform some sort of test that determines if code breaks
// when values are multiplied instead of divided.
}
[TestMethod]
[HostType("Moles")]
[ExpectedException(typeof(DivideByZeroException))]
public void Test3()
{
ArrangeScenario(Scenarios.DivideByZero);
var target = new PexMoleDemo.MyOtherClass();
var math = new PexMoleDemo.MyMath() { left = 1, right = 2 };
var left = math.left;
var right = math.right;
var actual = target.Divide();
}
[TestMethod]
[HostType("Moles")]
public void Test4()
{
ArrangeScenario(Scenarios.MultiplyInsteadOfDivide);
// Perform some sort of test that determines if code breaks
// when values are multiplied instead of divided.
}
}
}