0

現在、コードを使用した次のメソッドがあります。

public bool SendMail(ref MailData data)
    SmtpClient smtpClient = this.smtpClient;
    Console.WriteLine("SMTP CLIENT: " + smtpClient.ToString());
    Console.WriteLine("SMTP PORT: " + smtpClient.Port);
    Console.WriteLine("SMTP HOST: " + smtpClient.Host);
}

次のテストコードで呼び出します。

 public class MockSmtpClient : SmtpClient {
    public virtual void Send(MailMessage mailMessage) {
    }
    public virtual string Host
    {
        get
        {
            return Host;
        }
    }
    public virtual int Port
    {
        get
        {
           return Port;
        }
    }
 }

 ... (actual testcode:) ...


 MailData mailData = new MailData {
   HostAddress = "mydomain.com",
 };

 var mockSmtpClient = A.Fake<MockSmtpClient>();
 var mailerMock = new Mailer();

 // Setup
 It.IsAny<SmtpDeliveryMethod>())).Returns(mockSmtpClient.Object);
 A.CallTo(() => mockSmtpClient.Host).Returns(mailData.HostAddress);
 A.CallTo(() => mockSmtpClient.Port).Returns(22);

 // Act
 mailerMock.smtpClient = mockSmtpClient;
 mailerMock.SendMail(ref mailData);
 Console.WriteLine("MOCK SMTP CLIENT FROM TEST: " + mockSmtpClient);
 Console.WriteLine("SMTP HOST FROM UT: " + mockSmtpClient.Host);
 Console.WriteLine("SMTP PORT FROM UT: " + mockSmtpClient.Port);

実際のコードでモック オブジェクトのホストとポートを呼び出すと、\

SMTP CLIENT: Faked ServiCommTests.MockSmtpClient
SMTP PORT: 25
SMTP HOST: 

ただし、テスト コードからモックのプロパティを呼び出すと、正しいスタブ プロパティが返されます。

MOCK SMTP CLIENT FROM TEST: Faked ServiCommTests.MockSmtpClient
SMTP HOST FROM UT: mydomain.com
SMTP PORT FROM UT: 22

ご覧のとおり、実際のコードではホストもデフォルト ポートも返されませんが、テストコードではモック フレームワークから正しいスタブ プロパティが返されますが、オブジェクトは両方の環境で同じです。

(例のように) FakeItEasy の代わりにモッキング フレームワーク Moq を使用した場合もまったく同じです。

前もって感謝します。

4

2 に答える 2

1

@StevenScott が言うように、いくつかの制限付きでクラスをモックできます。あなたが説明した動作は、FakeItEasy での失敗のためではなく、実装して使用した方法によるものですMockSmtpClient

HostとプロパティはPort、 の同じプロパティを非表示にしSmtpClientます。これは、以下の警告で確認できます。

ここに画像の説明を入力

したがってmockSmtpClient、コンパイラが であることを認識している状況でアクセスするMockSmtpClient、新しいメソッドが呼び出されます。テストでは、これは FakeItEasy が提供する動作が実行されることを意味します。

ただし、製品コードはオブジェクトを としてしか認識していSmtpClientないため、クラスの (非仮想) メソッドが実行されます。

実演するために、FakeItEasy を写真から完全に取り出してみましょうMockSmtpClient

public class MockSmtpClient : SmtpClient
{
    public virtual void Send(MailMessage mailMessage)
    {
    }

    public virtual string Host
    {
        get { return "mocksmtpclient.local"; }
    }

    public virtual int Port
    {
        get { return 17; }
    }
}

そしてこのテスト:

[Test]
public void Test2()
{
    MailData mailData = new MailData
    {
        HostAddress = "mydomain.com",
    };

    var mockSmtpClient = new MockSmtpClient();
    var mailerMock = new Mailer();

    // Act
    mailerMock.smtpClient = mockSmtpClient;
    mailerMock.SendMail(ref mailData);
    Console.WriteLine("SMTP CLIENT FROM TEST: " + mockSmtpClient);
    Console.WriteLine("SMTP HOST FROM TEST: " + mockSmtpClient.Host);
    Console.WriteLine("SMTP PORT FROM TEST: " + mockSmtpClient.Port);
}

これにより、次の出力が生成されます。

SMTP CLIENT: GighaQuestion.MockSmtpClient
SMTP HOST: 
SMTP PORT: 25
SMTP CLIENT FROM TEST: GighaQuestion.MockSmtpClient
SMTP HOST FROM TEST: mocksmtpclient.local
SMTP PORT FROM TEST: 17

mockSmtpClientこれは、 FakeItEasy を使用して作成したときの動作に似ています。

于 2015-03-30T11:59:30.707 に答える
1

MockSmtpClient クラスをインターフェイスに変更すると、うまくいくことがわかりました。Moq と Fakeiteasy は明らかに、通常のクラスのモックをサポートしていません。

于 2015-03-26T13:15:23.327 に答える