1

抽象構成クラスから継承するクラスがあり、各クラスは INI ファイル、XML、conf、または独自の形式のリーダーを実装します。FakeItEasy を使用してテスト対象のオブジェクトを作成する際に問題が発生しています。

私がテストしようとしているオブジェクトは、依存性注入を介して構成オブジェクトを使用するため、ReadString()、ReadInteger() などの関数を呼び出して構成設定を読み取ることができます。次に、場所のテキスト (セクション、キーのインスタンス、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 に対して使用するさまざまな呼び出しの戻り値を制御できません。

パラメータの where と test という 2 つの方法をどのように組み合わせることができますか?

要求に応じた追加の定義:

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();
    }
}
4

1 に答える 1

2

あなたは

現在のプロキシ ジェネレータは、次の理由により、指定されたメソッドをインターセプトできません: - 非仮想メソッドはインターセプトできません。

の 2 パラメータ バージョンを偽造しようとしているため、エラーが発生しますReadString仮想メンバー、抽象メンバー、またはインターフェイス メンバーのみを偽造できます。2 パラメーターの ReadString はこれらのいずれでもないため、偽造することはできません。仮想の 2 パラメータの ReadString を用意するか、3 パラメータの ReadString を偽造する必要があると思います。

あなたの例は、特にそれを使用しているため、3パラメーターのReadStringを偽造する方向に私を駆り立てますGetLoginSequence。次に、(メソッド名の文字列ではなく)式を使用して制約するだけで、すべてうまくいくと思います。

私はあなたのコードの一部 (主に更新前のもの) を使って少しテストを行い、3 パラメーターの 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");
}
于 2013-08-16T18:50:43.080 に答える