我有一个从抽象Configuration类继承的类,然后每个类为INI文件,XML,conf或专有格式实现读取器。我在使用FakeItEasy创建要测试的对象时遇到问题。
我尝试测试的对象通过依赖注入使用配置对象,因此它可以通过调用ReadString(),ReadInteger()等函数,然后通过位置文本(Section,Key for例如,使用INI的实例)可以以任何格式的配置文件(INI,XML,conf等)从相应的节中检索。
使用的示例代码:
public class TestFile
{
private readonly ConfigurationSettings ConfigurationController_ ;
...
public TestFile(ConfigurationSettings ConfigObject)
{
this.ConfigurationController_ = ConfigObject;
}
public TestFile(XMLFile ConfigObject)
{
this.ConfigurationController_ = ConfigObject;
}
public TestFile(INIFile ConfigObject)
{
this.ConfigurationController_ = ConfigObject;
}
...
private List<string> GetLoginSequence()
{
List<string> ReturnText = new List<string>();
string SignOnFirst = ConfigurationController_.ReadString("SignOn", "SignOnKeyFirst", "Y");
string SendEnterClear = ConfigurationController_.ReadString("SignOn", "SendEnterClear", "N");
if (SendEnterClear.Equals("Y", StringComparison.CurrentCultureIgnoreCase))
{
ReturnText.Add("enter");
ReturnText.Add("clear");
}
if (SignOnFirst.Equals("N", StringComparison.CurrentCultureIgnoreCase))
{
ReturnText.AddRange(MacroUserPassword("[$PASS]"));
ReturnText.Add("sign_on");
}
else
{
ReturnText.Add("sign_on");
ReturnText.AddRange(MacroUserId("[$USER]"));
ReturnText.AddRange(MacroUserPassword("[$PASS]"));
}
return ReturnText;
}
一个简单的测试示例:
[TestMethod]
public void TestSignOnSequence()
IniReader FakeINI = A.Fake<IniReader>();
//Sample Reads:
//Config.ReadString("SignOn", "SignOnKeyFirst", "Y");
//Config.ReadString("SignOn", "SendEnterClear", "N"); // Section, Key, Default
A.CallTo(() => FakeINI.ReadString(A<string>.That.Matches(s => s == "SignOn"), A<string>.That.Matches(s => s == "SendEnterClear"))).Returns("N");
A.CallTo(() => FakeINI.ReadString(A<string>.That.Matches(s => s == "SignOn"), A<string>.That.Matches(s => s == "SignOnKeyFirst"))).Returns("N");
A.CallTo(FakeINI).Where( x => x.Method.Name == "ReadInteger").WithReturnType<int>().Returns(1000);
TestFile TestFileObject = new TestFile(FakeINI);
List<string> ReturnedKeys = TestFileObject.GetLoginSequence();
Assert.AreEqual(2, ReturnedKeys.Count, "Ensure all keystrokes are returned");
这样编译就可以了,但是当我执行代码时,出现以下异常:
Test threw Exception:
FakeItEasy.Configuration.FakeConfigurationException:
The current proxy generator can not intercept the specified method for the following reason:
- Non virtual methods can not be intercepted.
如果我更改了创建伪造品的方式,该伪造品将毫无例外地工作,那么对于同一函数的各种调用,我将无法获得不同的值。
A.CallTo(FakeINI).Where( x => x.Method.Name == "ReadString").WithReturnType<string>().Returns("N");
上面的方法不允许我控制该函数用于INI的不同调用的返回。
如何结合这两种方法,参数的位置和测试?
要求的其他定义:
public abstract class ConfigurationSettings
{
...
abstract public int ReadInteger(string Section, string Key, int Default);
abstract public string ReadString(string Section, string Key, string Default);
public int ReadInteger(string Section, string Key)
{ return ReadInteger(Section, Key, 0); }
public int ReadInteger(string Key, int Default)
{ return ReadInteger("", Key, Default); }
public int ReadInteger(string Key)
{ return ReadInteger(Key, 0); }
public string ReadString(string Section, string Key)
{ return ReadString(Section, Key, null); }
}
public class IniReader : ConfigurationSettings
{
...
public IniReader()
{
}
public IniReader(string PathAndFile)
{
this.PathAndFileName = PathAndFile;
}
public override int ReadInteger(string Section, string Key, int Default)
{
return GetPrivateProfileInt(Section, Key, Default, PathAndFileName);
}
public override string ReadString(string Section, string Key, string Default)
{
StringBuilder WorkingString = new StringBuilder(MAX_ENTRY);
int Return = GetPrivateProfileString(Section, Key, Default, WorkingString, MAX_ENTRY, PathAndFileName);
return WorkingString.ToString();
}
}
最佳答案
你正在
由于以下原因,当前代理生成器无法拦截指定的方法:
-无法拦截非虚拟方法。
错误,因为您试图伪造ReadString
的2参数版本。 Only virtual members, abstract members, or interface members can be faked。由于您的两个参数ReadString都不是,因此不能伪造。我认为您应该具有虚拟的2参数ReadString或伪造3参数ReadString。
您的示例将我推向伪造3参数ReadString的角色,尤其是因为GetLoginSequence
使用该参数。然后,我认为您可以只使用表达式(而不是方法名称字符串)来约束,并且都可以解决。
我对您的代码进行了一些测试(大部分来自更新之前),并成功伪造了三参数ReadString:
[Test]
public void BlairTest()
{
IniReader FakeINI = A.Fake<IniReader>();
A.CallTo(() => FakeINI.ReadString("SignOn", "SendEnterClear", A<string>._)).Returns("N");
A.CallTo(() => FakeINI.ReadString("SignOn", "SignOnKeyFirst", A<string>._)).Returns("N");
// Personally, I'd use the above syntax for this one too, but I didn't
// want to muck too much.
A.CallTo(FakeINI).Where(x => x.Method.Name == "ReadInteger").WithReturnType<int>().Returns(1000);
TestFile TestFileObject = new TestFile(FakeINI);
List<string> ReturnedKeys = TestFileObject.GetLoginSequence();
Assert.AreEqual(2, ReturnedKeys.Count, "Ensure all keystrokes are returned");
}