Unit testing 在使用Rhino Mock运行测试之前,如何测试需要调用以设置对象的方法?
我在测试这个场景时遇到问题 发票有两种状态-已完成和未完成-我想测试方法Presenter.FinishInvoice()是否调用DAO.FinishInvoice(),然后调用DAO.GetInvoice(),然后使用结果设置View.invoice。问题是,我需要调用DAO.GetInvoice()以首先获得要完成的发票,这是从Presenter.InitializeView()调用的(在另一个测试中测试) 这是我的测试:Unit testing 在使用Rhino Mock运行测试之前,如何测试需要调用以设置对象的方法?,unit-testing,rhino-mocks,mvp,Unit Testing,Rhino Mocks,Mvp,我在测试这个场景时遇到问题 发票有两种状态-已完成和未完成-我想测试方法Presenter.FinishInvoice()是否调用DAO.FinishInvoice(),然后调用DAO.GetInvoice(),然后使用结果设置View.invoice。问题是,我需要调用DAO.GetInvoice()以首先获得要完成的发票,这是从Presenter.InitializeView()调用的(在另一个测试中测试) 这是我的测试: using (mocks.Record()) { Setup
using (mocks.Record())
{
SetupResult.For(view.Invoice).PropertyBehavior();
SetupResult.For(DAO.GetInvoice(1)).Return(invoice);
Expect.Call(DAO.FinishInvoice(1)).Return(true);
Expect.Call(DAO.GetInvoice(1)).Return(invoice);
}
using (mocks.Playback())
{
Presenter presenter = new Presenter(view, DAO);
presenter.InitializeView(1);
presenter.FinishInvoice();
}
调用InitializeView()时,将调用DAO.GetInvoice()并查看.Invoice设置一次。这不是测试的一部分,但如果我不将View.Invoice设置为未完成的发票,FinishInvoice()将失败,因此需要设置返回值
对DAO.GetInvoice()的第二个调用是从FinishInvoice()调用的,并且是测试的一部分
如果我运行这个测试,我会在DAO.GetInvoice(1)上失败;预期为1,实际为0。我已经详细介绍了代码,它在调用FinishInvoice()时确实调用了DAO.GetInvoice(),所以一定是我的测试代码出错了,而不是我的演示者代码
如果我改变:
SetupResult.For(DAO.GetInvoice(1)).Return(invoice);
致:
它可以工作,但不应该是测试的一部分,因为它只是设置所需的(但不能放在设置方法中,因为并非所有测试都需要它)
我想我需要使用Expect.Call()来实现这一点并不是一场灾难,但我想学习如何按照我的要求来设置它。既然您想测试DAO类的交互,就需要创建它。这意味着您不能对其使用SetupResult 如果不关心方法调用的顺序,可以使用: 如果您确实关心方法调用的顺序,则必须使用以下命令明确指定每个期望: 然而,如果您在代码中两次调用DAO.GetInvoice,我会说这是一种代码味道,您可能应该考虑将其重构为一次调用 此外,以下是使用以下各项时的情况: 正如您所看到的,这要好得多,您甚至可以将模拟用作模拟和存根。调用GetInvoice()两次的原因是FinishInvoice()调用一个存储过程来更改发票,因此您需要重新获取它以显示更改。此外,这只是一个测试,没有显示两次调用GetInvoice()之间的时间线。您可以加载发票、查看发票、更改发票、完成发票,然后重新加载发票以查看完成发票可能会做出的更改。在我的测试代码中,视图和dao都是模拟-我不知道您不能在模拟上使用SetupResult.For()。我会多读一些关于这个话题的书。谢谢
Expect.Call(DAO.GetInvoice(1)).Return(invoice);
using (mocks.Record())
{
SetupResult.For(view.Invoice).PropertyBehavior();
Expect.Call(DAO.FinishInvoice(1)).Return(true);
Expect.Call(DAO.GetInvoice(1)).Return(invoice).Repeat.Any();
}
using (mocks.Playback())
{
Presenter presenter = new Presenter(view, DAO);
presenter.InitializeView(1);
presenter.FinishInvoice();
}
using (mocks.Record())
{
SetupResult.For(view.Invoice).PropertyBehavior();
using (mocks.Ordered())
{
Expect.Call(DAO.GetInvoice(1)).Return(invoice);
Expect.Call(DAO.FinishInvoice(1)).Return(true);
Expect.Call(DAO.GetInvoice(1)).Return(invoice);
}
}
using (mocks.Playback())
{
Presenter presenter = new Presenter(view, DAO);
presenter.InitializeView(1);
presenter.FinishInvoice();
}
//Arrange
DAO.Stub( x => x.GetInvoice(1) ).Return(true).Repeat.Any();
//Act
Presenter presenter = new Presenter(view, DAO);
presenter.InitializeView(1);
presenter.FinishInvoice();
//Assert
DAO.AssertWasCalled( x => x.FinishInvoice(1) );
DAO.AssertWasCalled( x=> x.GetInvoice(1) );