私はレガシーコード(ここでは「単体テストなしのコード」を意味する)についていくつかのテストを行っています。ときどき良い習慣が続くが、しばしば時間がない。私はこの場合に何をする必要があるかを理解することができませんでした。Moq:複数の継承を持つクラスをモックする
具体的なクラスで必要なメソッドをテストできるようにする必要がありますが、私がテストしているクラスのコンストラクタではできないため、私は模擬できるインターフェイスのパラメータだけでなく、独自の依存関係を持つ別の基底クラスから継承します。
私がテストしたいメソッドは、FilterController.SomeMethod(whatever_params)です。 FilterControllerはBaseControllerから継承します。そして、単純なインターフェイスIFilterControllerを追加して、FilterControllerがBaseControllerとIFilterControllerの両方から継承するようにしました。私がインターフェースに持っている唯一の方法は、テストしたいメソッドです( "SomeMethod")。
今、FilterControllerのコンストラクタは、BaseControllerにジャンプするときに問題に取り組んでいます。
public interface IFilterController { ActionResult SomeMethod(string s, bool b) }
public class FilterController : BaseController, IFilterController {
public FilterController(IFoo1 foo1, IFoo2 foo2, IFoo3 foo3, IFoo4 foo4)
: base(typeof(FilterController), foo1, foo2, foo3, foo4) {}
public ActionResult SomeMethod(string s, bool b) { // implementation }
// and the BaseController...
public BaseController(Type type, IFoo1 foo1, IFoo2 foo2, IFoo3 foo3, IFoo4 foo4)
{
// call that blows up due to not knowing how to mock the call inside here
_somePrivateProperty = _someOtherInterface.someCallThatIsntMocked(some_params)
// other stuff
}
私は現在、(FluentAssertionsと部品番号でMSTestを)設定するユニットテストを試みるために持っているコード:
private FilterController filterController;
private Mock<IFilterController> filterControllerMock;
private Mock<IFoo1> foo1mock;
private Mock<IFoo2> foo2mock;
private Mock<IFoo3> foo3mock;
private Mock<IFoo4> foo4mock;
[ClassInitialize]
public static void ClassInit(TestContext context) {}
[TestInitialize]
public void Initialize()
{
filterControllerMock = new Mock<IFilterController>();
foo1mock = new Mock<IFoo1>();
foo2mock = new Mock<IFoo2>();
foo3mock = new Mock<IFoo3>();
foo4mock = new Mock<IFoo4>();
// here is where the test bombs out with exceptions due to the base class making calls to stuff not mocked
filterController = new FilterController(foo1mock.Object, foo2mock.Object, foo3mock.Object, foo4mock.Object);
}
[TestCleanup]
public void Cleanup(){}
[ExpectedException(typeof(CustomException))]
[TestMethod]
public void SomeMethod_ForcedErrorScenario_CatchesCustomException()
{
// Arrange
filterControllerMock
.Setup(x => x.SomeMethod(It.IsAny<string>(), It.IsAny<bool>()))
.Returns(new CustomException());
// Act
var result = filterController.SomeMethod("Foobar", false);
}
この場合、私が扱っていることを確認作っていますするTry Catchブロックがありますcatchブロックに到達したときにバグを確認するために適切に修正されました。テストの目的のために例外がどのようにスローされても気にしません。ちょうどそれが捕らえられ、後で期待することをします。しかし、私が言ったように、継承元であるBaseControllerのために、具体的なメソッドを呼び出すためにFilterControllerコンストラクター自体をモックしようとすることはできません。
- EDIT:問題を解決しました。 BaseControllerでは、_someOtherInterfaceは、コンストラクタで渡されたインターフェイスの1つに基づいてインスタンス化されました。私のMSTest Initializeメソッドでは、インターフェイスがnull参照ではなく、Setup(x => x.otherMethod())で呼び出されたメソッドをオーバーライドするようにしなければなりませんでした。(_someOtherInterface.Object)。私はそれがfilterController =新しいFilterController(interfacemockを作成しようとしました前に、[TestInitialize]メソッドを初期化におけるので、それをしなければならなかった問題を解決するにはBaseController
// I didn't realize the _someOtherInterface was instantiated based off an interface passed in
_someOtherInterface = _IFoo1.AMethodNotMocked();
// many lines later...
_somePrivateProperty = _someOtherInterface.SomeMockedMethod()
に...私の問題を発見し
実際のアプリケーションはどのように '_someOtherInterface'をインスタンス化しますか?注射されていません。それを機能させるには、リファクタリングする必要があるようです。 – Jonesopolis
私はその部分を分かりました。コンストラクタで渡されたインタフェースの1つを呼び出し、他のインタフェースをインスタンス化してインスタンス化します。私は、呼び出すメソッドをオーバーライドするために、そのモックされたインターフェイスをセットアップするために、Initializeメソッドで呼び出しを追加しなければなりませんでした。私はOPを更新しますが、元の問題は解決されます。実際には、新しい問題はオリジナルから離れているので、むしろ新しいスレッドを作成することになります。私は私が最初にそれを理解することができるかどうか見るために、しばらくそれを解読します。 – user1709953
あなたが進歩していると聞いてうれしい – Jonesopolis