单元测试函数求 与犀牛制品投掷InvalidCastException的与第二期望()调用(U

2019-09-16 10:26发布

我的单元测试一类通过获取注入Autofac一些参数。

一些参数是Func<Delegate> 。 这使我能够创建多个代表使用。 请参阅此Autofac Wiki页面 ,如果你需要一个更好的描述。

下面是类的一部分。

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”的目的为类型“工厂”。

我不完全知道如何修复此问题。

Answer 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);


文章来源: Unit testing a Func with Rhino Mocks throwing InvalidCastException with second Expect() invocation