使用Rhino Mocks对Func 进行unit testing,并使用第二个Expect()调用抛出InvalidCastException

我正在测试一个获取Autofac注入的参数的类。

一些参数是Func 。 这允许我创建多个委托使用。 如果您需要更好的描述,请参阅此Autofac Wiki页面 。

这是课堂的一部分。

 public class CreateProductCommand : TransactionalDBCommandBase { public delegate CreateProductCommand Factory(ProductInfo info, IAppSecurityContext context); private ProductInfo _info; private Func _saveTextMasterCommandFactory; private Func _saveTextValueCommandFactory; private SaveProductCommand.Factory _saveProductCommand; public CreateProductCommand(ProductInfo info, Func saveTextMasterCommandFactory, Func saveTextValueCommandFactory, SaveProductCommand.Factory saveProductCommand, IAppSecurityContext context) { this._info = info; this._saveTextMasterCommandFactory = saveTextMasterCommandFactory; this._saveTextValueCommandFactory = saveTextValueCommandFactory; this._saveProductCommand = saveProductCommand; this.CurrentContext = context; } public override ProductImpl Execute(IDataTransaction dataTrans) { //More code here this._saveTextMasterCommandFactory().Invoke(SomeParam,SomeParam2).Execute(dataTrans); //Some time later this._saveTextMasterCommandFactory().Invoke(SomeDiffParam,SomeDiffParam2).Execute(dataTrans); } } 

测试类看起来像这样。 SetUp是巨大的。 我将对齐问题代码块的左侧。

 [TestFixture] public class CreateProductCommandTests { private IDataTransaction _dtMock; private IDataAccessAdapter _daaMock; private Func stmfMock; private Func stvfMock; private SaveProductCommand.Factory saveProductDelMock; private ProductInfo info; private IAppSecurityContext context; [SetUp] public void SetUp() { this._dtMock = MockRepository.GenerateMock(); this._daaMock = MockRepository.GenerateMock(); this._dtMock.Expect(m => m.DataAccessAdapter).Repeat.Any().Return(this._daaMock); stvfMock = MockRepository.GenerateMock<Func>(); stmfMock = MockRepository.GenerateMock<Func>(); context = new AppSecurityContext() { LanguageID = 1 }; info = new ProductInfo() { CatalogNumber = "CatalogNumber", BrandID = 1, ProductDescription = "ProductDescription", ProductName = "ProductName" }; //Mock the command var nameTextMaster = new TextMasterImpl() { AltTextMasterID = new Guid().ToString("N"), IsCoreAppText = false, TextMasterID = 1 }; var nameTextMasterMock = MockRepository.GenerateMock(null, null); nameTextMasterMock.Expect(m => m.Execute(Arg.Is.Equal(this._dtMock))).Return(nameTextMaster); //Mock the Delegate that creates it. var nameTextMasterFactoryMock = MockRepository.GenerateMock(); nameTextMasterFactoryMock.Expect(m => m(Arg.Is.Anything, Arg.Is.Anything)).Return(nameTextMasterMock); //This call here is fine. Passes with no problem. stmfMock.Expect(m => m()).Return(nameTextMasterFactoryMock); //NameTextValue Mocking. var nameTextValue = new TextValueImpl() { LanguageID = 1, ContentText = "NameTextValue", TextMasterID = 1, TranslationStatus = 0, TextValueID = 1 }; var nameTextValueMock = MockRepository.GenerateMock(null, null); nameTextValueMock.Expect(m => m.Execute(Arg.Is.Equal(this._dtMock))).Return(nameTextValue); var nameTextValueFactoryMock = MockRepository.GenerateMock(); nameTextValueFactoryMock.Expect(m => m(Arg.Matches(n => n.TextMasterID == nameTextMaster.TextMasterID && n.ContentText == info.ProductName), Arg.Is.Anything)).Return(nameTextValueMock); stvfMock.Expect(m => m()).Repeat.Once().Return(nameTextValueFactoryMock); //DescriptionTextMaster Mocking var descTextMaster = new TextMasterImpl() { AltTextMasterID = new Guid().ToString("N"), IsCoreAppText = false, TextMasterID = 2 }; var descTextMasterMock = MockRepository.GenerateMock(null, null); descTextMasterMock.Expect(m => m.Execute(Arg.Is.Equal(this._dtMock))).Return(descTextMaster); //Delegate mock var descTextMasterFactoryMock = MockRepository.GenerateMock(); descTextMasterFactoryMock.Expect(m => m(Arg.Is.Anything, Arg.Is.Anything)).Return(descTextMasterMock); //THIS call fails with an InvalidCastException stmfMock.Expect(m => m()).Return(descTextMasterFactoryMock); var descTextValue = new TextValueImpl() { LanguageID = 1, ContentText = "DescTextValue", TextValueID = 2, TextMasterID = 2, TranslationStatus = 0 }; var descTextValueMock = MockRepository.GenerateMock(null, null); descTextValueMock.Expect(m => m.Execute(Arg.Is.Equal(this._dtMock))).Return(descTextValue); var descTextValueFactoryMock = MockRepository.GenerateMock(); descTextValueFactoryMock.Expect(m => m(Arg.Matches(n => n.TextMasterID == descTextMaster.TextMasterID && n.ContentText == info.ProductDescription), Arg.Is.Anything)).Return(descTextValueMock); stvfMock.Expect(m => m()).Repeat.Once().Return(descTextValueFactoryMock); var product = new ProductImpl() { ProductNameTextID = nameTextMaster.TextMasterID, DescriptionTextID = descTextMaster.TextMasterID, CatalogNumber = info.CatalogNumber, ProductID = 1 }; var saveProductCommandMock = MockRepository.GenerateMock(null, null); saveProductCommandMock.Expect(m => m.Execute(Arg.Is.Equal(this._dtMock))).Return(product); saveProductDelMock = MockRepository.GenerateMock(); saveProductDelMock.Expect(m => m(Arg.Is.Equal(product), Arg.Is.Anything)).Return(saveProductCommandMock); } } 

例外情况是:无法将“ProxyDelegate_Factory_3Proxyef78e79dacee4c759351a5ffaa933f85”类型的对象强制转换为“工厂”类型。

我不确定如何解决这个问题。

此建议并非受到您收到的exception消息的特别启发,因此可能无济于事。 在我看来,你没有给模拟存储库提供足够的信息,但是:

 stmfMock.Expect(m => m()).Return(nameTextMasterFactoryMock); //... stmfMock.Expect(m => m()).Return(descTextMasterFactoryMock); 

你有同样的模拟期望Invoke相同的方法(即Invoke ),并且你告诉它返回两个不同的东西。 这个怎么样:

 stmfMock.Expect(m => m()).Repeat.Once().Return(nameTextMasterFactoryMock); //... stmfMock.Expect(m => m()).Repeat.Once().Return(descTextMasterFactoryMock);