Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#Rhino.Mocks-如何编写测试代码而不重复自己的工作?_C#_Unit Testing_Rhino Mocks - Fatal编程技术网

C#Rhino.Mocks-如何编写测试代码而不重复自己的工作?

C#Rhino.Mocks-如何编写测试代码而不重复自己的工作?,c#,unit-testing,rhino-mocks,C#,Unit Testing,Rhino Mocks,我希望在我的Rhino中删除所有依赖项。模拟单元测试,但我最终重复了我自己。随着依赖项的数量不断增加,我需要重新访问现有的单元测试,并需要添加依赖项。这令人不满意,也是我应该用另一种方式去做的信号 如果我只是将初始化移到一个单独的方法中,我将所有的模拟都传递到该方法中,而我什么也没有得到 有没有办法初始化Using(mocks.Record)并将其作为lambda表达式传递到方法中?或者你是怎么做到的 提前感谢您的评论 丹麦安德斯 [Test, Category("UnitTest")]

我希望在我的Rhino中删除所有依赖项。模拟单元测试,但我最终重复了我自己。随着依赖项的数量不断增加,我需要重新访问现有的单元测试,并需要添加依赖项。这令人不满意,也是我应该用另一种方式去做的信号

如果我只是将初始化移到一个单独的方法中,我将所有的模拟都传递到该方法中,而我什么也没有得到

有没有办法初始化Using(mocks.Record)并将其作为lambda表达式传递到方法中?或者你是怎么做到的

提前感谢您的评论

丹麦安德斯

    [Test, Category("UnitTest")]
    public void TestThatApplicationCanExitByDefault()
    {
        var mocks = new MockRepository();

        var workspaceViewModelProvider = mocks.StrictMock<IWorkspaceViewModelProvider>();
        var workspaceRepository = mocks.StrictMock<IWorkspaceService>();
        var userResponseProvider = mocks.StrictMock<IUserResponseProvider>();
        var versionProvider = mocks.StrictMock<IVersionProvider>();
        var eventAggregator = mocks.StrictMock<IEventAggregator>();
        var allowedLegacyImportProvider = mocks.StrictMock<IAllowedLegacyImportProvider>();
        var stateManager = mocks.StrictMock<IStateManager>();
        var currentWorkspaceChangedEvent = mocks.StrictMock<CurrentWorkspaceChangedEvent>();

        using (mocks.Record())
        {
            // constructor fires:
            eventAggregator
                .Stub(x => x.GetEvent<CurrentWorkspaceChangedEvent>())
                .Return(currentWorkspaceChangedEvent);

            currentWorkspaceChangedEvent
                .Stub(x => x.Subscribe(null))
                .IgnoreArguments();
        }

        var target = new MainWindowViewModel(
            workspaceViewModelProvider,
            workspaceRepository,
            userResponseProvider,
            versionProvider, eventAggregator, allowedLegacyImportProvider, stateManager);

        var canAppExit = target.CanAppExit();

        Assert.IsTrue(canAppExit);

        mocks.VerifyAll();
    }


    [Test, Category("UnitTest")]
    public void TestThatInsertProjectWorks()
    {
        var mocks = new MockRepository();

        var workspaceViewModelProvider = mocks.StrictMock<IWorkspaceViewModelProvider>();
        var workspaceRepository = mocks.StrictMock<IWorkspaceService>();
        var userResponseProvider = mocks.StrictMock<IUserResponseProvider>();
        var versionProvider = mocks.StrictMock<IVersionProvider>();
        var eventAggregator = mocks.StrictMock<IEventAggregator>();
        var allowedLegacyImportProvider = mocks.StrictMock<IAllowedLegacyImportProvider>();
        var stateManager = mocks.StrictMock<IStateManager>();
        var currentWorkspaceChangedEvent = mocks.StrictMock<CurrentWorkspaceChangedEvent>();
        var workspaceViewModel = mocks.StrictMock<IWorkspaceViewModel>();

        using (mocks.Record())
        {
            // constructor fires:
            eventAggregator
                .Stub(x => x.GetEvent<CurrentWorkspaceChangedEvent>())
                .Return(currentWorkspaceChangedEvent);

            currentWorkspaceChangedEvent
                .Stub(x => x.Subscribe(null))
                .IgnoreArguments();

            workspaceViewModelProvider
                .Stub(x => x.GetViewModel())
                .Return(workspaceViewModel);

            workspaceViewModel
                .Stub(x => x.InsertProject());
        }

        var target = new MainWindowViewModel(
            workspaceViewModelProvider,
            workspaceRepository,
            userResponseProvider,
            versionProvider, eventAggregator, allowedLegacyImportProvider, stateManager);

        target.InsertProject();

        mocks.VerifyAll();
    }
[测试,类别(“单元测试”)]
public void TestThatApplicationCanExitByDefault()
{
var mocks=new MockRepository();
var workspaceViewModelProvider=mocks.StrictMock();
var workspaceprepository=mocks.StrictMock();
var userResponseProvider=mocks.StrictMock();
var versionProvider=mocks.StrictMock();
var eventAggregator=mocks.StrictMock();
var allowedLegacyImportProvider=mocks.StrictMock();
var stateManager=mocks.StrictMock();
var currentWorkspaceChangedEvent=mocks.StrictMock();
使用(mocks.Record())
{
//建造商火灾:
事件聚合器
.Stub(x=>x.GetEvent())
.返回(currentWorkspaceChangedEvent);
CurrentWorkspaceChangeEvent
.Stub(x=>x.Subscribe(null))
.IgnoreArguments();
}
var target=新的MainWindowViewModel(
workspaceViewModelProvider,
工作空间存储库,
userResponseProvider,
versionProvider、eventAggregator、allowedLegacyImportProvider、stateManager);
var canAppExit=target.canAppExit();
Assert.IsTrue(canAppExit);
mocks.VerifyAll();
}
[测试,类别(“单元测试”)]
公共无效测试ThatInsertProjectWorks()
{
var mocks=new MockRepository();
var workspaceViewModelProvider=mocks.StrictMock();
var workspaceprepository=mocks.StrictMock();
var userResponseProvider=mocks.StrictMock();
var versionProvider=mocks.StrictMock();
var eventAggregator=mocks.StrictMock();
var allowedLegacyImportProvider=mocks.StrictMock();
var stateManager=mocks.StrictMock();
var currentWorkspaceChangedEvent=mocks.StrictMock();
var workspaceViewModel=mocks.StrictMock();
使用(mocks.Record())
{
//建造商火灾:
事件聚合器
.Stub(x=>x.GetEvent())
.返回(currentWorkspaceChangedEvent);
CurrentWorkspaceChangeEvent
.Stub(x=>x.Subscribe(null))
.IgnoreArguments();
workspaceViewModelProvider
.Stub(x=>x.GetViewModel())
.返回(workspaceViewModel);
工作空间视图模型
.Stub(x=>x.InsertProject());
}
var target=新的MainWindowViewModel(
workspaceViewModelProvider,
工作空间存储库,
userResponseProvider,
versionProvider、eventAggregator、allowedLegacyImportProvider、stateManager);
target.InsertProject();
mocks.VerifyAll();
}

尝试将基类与受保护的模拟对象一起使用,并使用[SetUp]/[TestFixtureSetUp](以NUnit为例)


明智的做法是,只将具有初始化的公共对象放在基类中-在同一个类中使用[SetUp]/[TestFixtureSetUp],其中存在多个单元测试,并且您需要模拟/初始化特定于此测试的内容。将所有内容都放在基础中也会增加单元测试的执行时间(至少它们执行的时间更长)。

我倾向于使用一个helper方法来构建模拟,这个方法需要一个lambda。然后,lambda可以将模拟与测试进行通信。我对testhelper方法进行了重载,以形成一个API,从而限制了哪些mock可用于测试。通过这种方式,模拟构建可以集中化,从而最大限度地减少测试中的依赖性践踏

举个例子就更明显了。这使用最小起订量,但技术是通用的

    private static void RunTest(Action<IThing1> test)
    {
        RunTest(test: (thing1, thing2, thing3) => test(thing1));
    }

    private static void RunTest(Action<IThing1, IThing2> test)
    {
        RunTest(test: (thing1, thing2, thing3) => test(thing1, thing2));
    }

    private static void RunTest(Action<IThing1, IThing2, IThing3> test)
    {
        IThing1 thing1 = new Mock<IThing1>().Object;
        IThing2 thing2 = new Mock<IThing2>().Object;
        IThing3 thing3 = new Mock<IThing3>().Object;

        test(thing1, thing2, thing3);
    }

    [Test]
    public void do_some_stuff_to_a_thing()
    {
        RunTest(test: thing1 => {
            //Do some testing....
        });
    }

    [Test]
    public void do_some_stuff_to_things()
    {
        RunTest(test: (thing1, thing2) => {
            //Do some testing....
        });
    }
私有静态无效运行测试(操作测试)
{
运行测试(test:(thing1,thing2,thing3)=>测试(thing1));
}
专用静态无效运行测试(动作测试)
{
运行测试(test:(thing1,thing2,thing3)=>测试(thing1,thing2));
}
专用静态无效运行测试(动作测试)
{
i thing1 thing1=新建Mock().Object;
i thing2 thing2=新建Mock().Object;
i thing3 thing3=新建Mock().Object;
测试(第1件、第2件、第3件);
}
[测试]
公共空间做一些事情
{
运行测试(测试:thing1=>{
//做一些测试。。。。
});
}
[测试]
公共空间做一些事情
{
RunTest(test:(thing1,thing2)=>{
//做一些测试。。。。
});
}

我喜欢比被测代码更难理解的单元测试(我也不只是挑出你的,我的!)是的-它肯定比被测代码更复杂;-)也许测试告诉了你一些事情#1) 依赖关系太多?如果可能的话,您可以从依赖项列表聚合集群,或者将其中一些集群向下移动到方法参数中#2) 您是否需要所有这些模拟来测试CanAppExit()?如果依赖项与测试无关,则传入null。是的,我将避免将依赖项作为参数传递。这对您有用吗?我几乎总是使用基类进行单元测试。我无法想象有1000多个单元测试和大量重复的代码。嗨,darjan,我真的认为你给出了一个完美的答案,但其中一个必须得到正确的答案…整洁!这正是我想要的@安德斯很高兴这有帮助