我希望在我的Rhino.Mocks单元测试中存根所有依赖项,但我最终重复了一遍。随着依赖项数量的不断增加,我需要重新访问现有的单元测试,并需要添加依赖项。这是令人不满意的,也是我应该以另一种方式做到这一点的信号。
如果我只是将初始化移动到一个单独的方法,我将所有的模拟传递给它,我什么也没做到。
有没有办法初始化然后将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();
}
答案 0 :(得分:3)
我倾向于有一个辅助方法来负责构建我的模拟,这个方法需要一个lambda。然后lambda可以将模拟传达给测试。我有测试助手方法的重载来形成API,从而限制测试可用的模拟。通过这种方式,模拟构建可以集中化,从而最大限度地减少测试中的依赖性。
一个例子更明显。这使用Moq,但技术很通用。
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....
});
}
答案 1 :(得分:2)
尝试使用带有受保护模拟对象的基类,并使用[SetUp] / [TestFixtureSetUp](例如使用NUnit)。
明智的做法是只将具有初始化的公共对象放到基类中 - 在同一个类中使用[SetUp] / [TestFixtureSetUp],其中有多个单元测试,并且您需要模拟/初始化仅针对此测试的特定内容。把所有东西放在你的基地也会使你的单元测试膨胀(至少他们执行的时间更长)。