2012-04-09 83 views
0

我正在测试一个类,它获取Autofac注入的一些参数。单元测试Func <Delegate> Rhino Mocks抛出InvalidCastException和第二个Expect()调用

一些参数是Func<Delegate>。这使我可以创建多个代表使用。如果您需要更好的描述,请参阅this Autofac Wiki page

下面是类的一部分。

public class CreateProductCommand : TransactionalDBCommandBase<ProductImpl> 
{ 
    public delegate CreateProductCommand Factory(ProductInfo info, IAppSecurityContext context); 

    private ProductInfo _info; 
    private Func<SaveTextMasterCommand.Factory> _saveTextMasterCommandFactory; 
    private Func<SaveTextValueCommand.Factory> _saveTextValueCommandFactory; 
    private SaveProductCommand.Factory _saveProductCommand; 

    public CreateProductCommand(ProductInfo info, Func<SaveTextMasterCommand.Factory> saveTextMasterCommandFactory, 
     Func<SaveTextValueCommand.Factory> 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); 
    } 
} 

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

[TestFixture] 
    public class CreateProductCommandTests 
    { 
     private IDataTransaction _dtMock; 
     private IDataAccessAdapter _daaMock; 

     private Func<SaveTextMasterCommand.Factory> stmfMock; 
     private Func<SaveTextValueCommand.Factory> stvfMock; 
     private SaveProductCommand.Factory saveProductDelMock; 
     private ProductInfo info; 
     private IAppSecurityContext context; 

     [SetUp] 
     public void SetUp() 
     { 
      this._dtMock = MockRepository.GenerateMock<IDataTransaction>(); 
      this._daaMock = MockRepository.GenerateMock<IDataAccessAdapter>(); 
      this._dtMock.Expect(m => m.DataAccessAdapter).Repeat.Any().Return(this._daaMock); 
      stvfMock = MockRepository.GenerateMock<Func<SaveTextValueCommand.Factory>>(); 
      stmfMock = MockRepository.GenerateMock<Func<SaveTextMasterCommand.Factory>>(); 
      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<SaveTextMasterCommand>(null, null); 
      nameTextMasterMock.Expect(m => m.Execute(Arg<IDataTransaction>.Is.Equal(this._dtMock))).Return(nameTextMaster); 

      //Mock the Delegate that creates it. 
      var nameTextMasterFactoryMock = MockRepository.GenerateMock<SaveTextMasterCommand.Factory>(); 
      nameTextMasterFactoryMock.Expect(m => m(Arg<TextMasterImpl>.Is.Anything, Arg<IAppSecurityContext>.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<SaveTextValueCommand>(null, null); 
      nameTextValueMock.Expect(m => m.Execute(Arg<IDataTransaction>.Is.Equal(this._dtMock))).Return(nameTextValue); 

      var nameTextValueFactoryMock = MockRepository.GenerateMock<SaveTextValueCommand.Factory>(); 
      nameTextValueFactoryMock.Expect(m => m(Arg<TextValueImpl>.Matches(n => n.TextMasterID == nameTextMaster.TextMasterID && n.ContentText == info.ProductName), 
       Arg<IAppSecurityContext>.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<SaveTextMasterCommand>(null, null); 
      descTextMasterMock.Expect(m => m.Execute(Arg<IDataTransaction>.Is.Equal(this._dtMock))).Return(descTextMaster); 

      //Delegate mock 
      var descTextMasterFactoryMock = MockRepository.GenerateMock<SaveTextMasterCommand.Factory>(); 
      descTextMasterFactoryMock.Expect(m => m(Arg<TextMasterImpl>.Is.Anything, Arg<IAppSecurityContext>.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<SaveTextValueCommand>(null, null); 
      descTextValueMock.Expect(m => m.Execute(Arg<IDataTransaction>.Is.Equal(this._dtMock))).Return(descTextValue); 

      var descTextValueFactoryMock = MockRepository.GenerateMock<SaveTextValueCommand.Factory>(); 
      descTextValueFactoryMock.Expect(m => m(Arg<TextValueImpl>.Matches(n => n.TextMasterID == descTextMaster.TextMasterID && n.ContentText == info.ProductDescription), 
       Arg<IAppSecurityContext>.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<SaveProductCommand>(null, null); 
      saveProductCommandMock.Expect(m => m.Execute(Arg<IDataTransaction>.Is.Equal(this._dtMock))).Return(product); 

      saveProductDelMock = MockRepository.GenerateMock<SaveProductCommand.Factory>(); 
      saveProductDelMock.Expect(m => m(Arg<ProductImpl>.Is.Equal(product), Arg<IAppSecurityContext>.Is.Anything)).Return(saveProductCommandMock); 
     } 
} 

例外是:无法转换类型“ProxyDelegate_Factory_3Proxyef78e79dacee4c759351a5ffaa933f85”的目的为类型“工厂”。

我不完全知道如何得到这个固定。

回答

1

这个建议并没有特别的您会收到异常消息鼓舞,所以它可能不会帮助。在我看来,你没有给予足够的信息来模拟仓库,但是:

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

你已经得到了相同的模拟期待同样的方法被调用(即Invoke),而你告诉它返回两个不同的东西。这个怎么样:

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

绝对错过了这一点,但它仍然没有摆脱例外。 – DavidAndroidDev 2012-04-09 21:44:50

+0

我看过了你的代码几次,我找不到任何理由的代理不会从正确的'Factory'类型继承。我会尝试使用一个存储库实例,而不是静态的'Generate ...'方法;我通常会发现这种方法工作更顺利,但这可能是因为我更熟悉这种方法。 – phoog 2012-04-09 22:16:41

+0

你确实引导我走向正确的方向。我用一种方式重写了它,以避免对这个对象产生两个期望,并且我能够支持它。谢谢! – DavidAndroidDev 2012-04-09 22:57:07