Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.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
Unit testing 在使用Rhino Mock运行测试之前,如何测试需要调用以设置对象的方法?_Unit Testing_Rhino Mocks_Mvp - Fatal编程技术网

Unit testing 在使用Rhino Mock运行测试之前,如何测试需要调用以设置对象的方法?

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

我在测试这个场景时遇到问题

发票有两种状态-已完成和未完成-我想测试方法Presenter.FinishInvoice()是否调用DAO.FinishInvoice(),然后调用DAO.GetInvoice(),然后使用结果设置View.invoice。问题是,我需要调用DAO.GetInvoice()以首先获得要完成的发票,这是从Presenter.InitializeView()调用的(在另一个测试中测试)

这是我的测试:

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