2

CIRCLE と呼ばれるクラスと、SQUARE と呼ばれる別のクラスがあるとします。これらの各クラスには、area というパブリック関数があります。(それぞれ円の面積と正方形の面積を計算します。)

クラスiMathもあります。このクラスには、関数ADDがあります

    Public Function ADD(byval c as CIRCLE, byval s as SQUARE) 
       Return c.area() + s.area()
    End Function 

ここで、ADD 関数の単体テストを行います。明らかに、この非常に簡単な問題では、円オブジェクトと正方形オブジェクトを簡単に作成して、ADD 関数の単体テストを行うことができます。ただし、私の Circle オブジェクトと Square オブジェクトが非常に複雑なオブジェクトであり、オブジェクトを作成するのが非常に難しいと仮定しましょう。これらは他の多くの依存関係を継承して含んでいるためです。このような場合には、

  1. CIRCLE および SQUARE オブジェクトを偽造するにはどうすればよいですか? (注: CIRCLE および SQUARE クラスには、パラメータのない Public Sub New はありません)

  2. CIRCLE および SQUARE オブジェクトの面積関数の結果を偽造するにはどうすればよいですか (ADD 関数をテストするために数値が必要なだけで、面積がどのように計算されるかは気にしません)

4

2 に答える 2

2

CIRCLEおよびSQUAREclassesのすべてのメンバーを作成するとOverridable、それらを継承し、すべてのメンバーをスタブでオーバーライドできます。たとえば、次のようになります。

Public Class Circle
    Public Overridable Function Area() As Integer
        ' Complicated logic
    End Function
End Class

Public Class MockCircle
    Inherits Circle

    Public Overrides Function Area() As Integer
        Return 10
    End Function
End Class

ただし、元のクラスのコンストラクターに作成が困難なパラメーターが多数必要な場合、クラスは引き続き基本コンストラクターを呼び出す必要があるCIRCLEため、それは役に立ちません。MockCircle

望ましい解決策は、インターフェイスを使用することです。ADDメソッドに具象オブジェクトを受け入れる代わりに、代わりにインターフェースCIRCLEを実装するオブジェクトを要求させます。ICircle

Public Interface ICircle
    Function Area() As Integer
End Interface

Public Class Circle
    Implements ICircle

    Public Function Area() As Integer Implements ICircle.Area
        ' Complicated logic
    End Function
End Class

Public Class MockCircle
    Implements ICircle

    Public Function Area() As Integer Implements ICircle.Area
        Return 10
    End Function
End Class

Public Class MyMath
    Public Function Add(c As ICircle, s As ISquare) As Integer
        Return c.Area() + s.Area()
    End Function
End Class

CIRCLEこれで、がそのコンストラクターで何を必要としているかは問題ではなくなりました。これで、メソッドにオブジェクトまたはオブジェクトのいずれかを指定でき、ADDどちらの方法でも機能します。オブジェクトは から継承しないため、複雑な依存関係を共有しません。この方法論には実は便利な名前もあります。これは、依存性注入 (DI) と呼ばれます。多くの単体テストを行う場合は、時間をかけて DI に関する調査を行う価値があります。理想的には、クラスの依存関係もすべてインターフェイスを介して行われるため、依存関係のすべてのモック オブジェクトを与えることで、オブジェクトを簡単に作成することもできます。CIRCLEMockCircleMockCircleCIRCLECIRCLECIRCLE

コードの表面的な問題についても言及する義務があると感じています。.NET フレームワークおよび Microsoft 標準との一貫性を保つために、すべてのメソッドとクラス名に PascalCase を使用する必要があります。したがって、たとえば、それはAddではなく である必要があり、 andではなくandADDである必要があります。また、クラス名は文字「i」で始まらないでください。Microsoft の標準によれば、型名の先頭に「I」を付けると、それがクラスではなくインターフェイスであることを意味します。最後の問題は、関数が戻り値の型を指定していないことです。すべての関数の戻り値の型を常に指定する必要があります。たとえば、私の例では、 return に変更しました。CircleSquareCIRCLESQUAREiMathADDAs Integer

于 2013-08-13T12:21:19.537 に答える
1

その問題を正確に解決する既存のモック フレームワークに依存する必要があります。私のお気に入りの 1 つはNSubsituteです。

仮想関数を持つクラスの任意のインターフェイスのモックを作成できます。そして一般的には、手動のモックを作成するよりも望ましいです。

于 2013-08-22T07:33:01.970 に答える