使用Rhino mock进行单元测试 [英] Unit Testing Using Rhino mock

查看:122
本文介绍了使用Rhino mock进行单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我是单元测试的新手。通过互联网后,我决定使用rhino mock进行单元测试。我在我的项目中使用存储库和uow模式。现在让我从我的控制器类开始。我喜欢这个

Hi,
I am new to unit testing. After going through the internet I decided to use rhino mock for unit testing. I am using repository and uow pattern in my project. Now let me start from my controller class. I have like this

private readonly IRoomTypeService _roomTypeService;

       public RoomTypeController(IRoomTypeService roomTypeService)
       {
           this._roomTypeService = roomTypeService;
       }

       public RoomTypeController()
       {

       }





现在我的服务接口类如下所示



Now my service interface class is like below

 public interface IRoomType : IEntityRepository<RoomType>
    {
    }

Repository class something like this
 public class RoomTypeRepository : EntityRepositoryBase<RoomType>, IRoomType
    {
        public RoomTypeRepository(IDBFactory databaseFactory)
            : base(databaseFactory)
        {
        }





当我运行应用程序但使用rhino mocks进行单元测试时,一切正常我无法获取数据也不将数据保存到数据库中。





Everything works fine when I run the application but while doing unit test using rhino mocks I couldn't get data nor save data into database.

private IRoomType roomTypeRepositoryMock { get; set; }
       private IUnitOfWork uowRepositoryMock { get; set; }

       [TestInitialize]
       public void Initialize()
       {
           roomTypeRepositoryMock = MockRepository.GenerateMock<IRoomType>();
           uowRepositoryMock = MockRepository.GenerateMock<IUnitOfWork>();
       }


       [TestMethod]
       public void InsertRoomType()
       {


           RoomType roomType = new RoomType()
           {
               RoomType1="R1",
               NoofBeds=2,
               IsTVAvailable=false,
               IsACAvailable=false,
               OtherFacilitiesAvailable="NA"
           };

           var roomTypeService = CreateRoomTypeService();
           roomTypeService.CreateRoomType(roomType);

       }

       private RoomTypeService CreateRoomTypeService()
       {
           return new RoomTypeService(roomTypeRepositoryMock, uowRepositoryMock);
       }
   }



关于单元测试的基本想法,我已经完成了这段代码。任何人都可以帮我解决这个问题。


With basic ideas on unit testing I have done this code. Could any one help me to solve this issue.

推荐答案

问题是你没有指定模拟应该做什么。单元测试中模拟的目的是为测试提供已知的环境。关键是你需要不变的输入,这样你就可以将输出与你的期望进行比较。



假设你想测试RoomTypeService的CreateRoomType()方法。我会在这里简化你的代码。但是你没有在那里显示相关部分:

The problem is you didn't specify what the mocks should do. The purpose of a mock in a unit test is to provide a known environment for the test. The point is you need invariant inputs so you can then compare the outputs to your expectations.

Let's assume you want to test the CreateRoomType() method of RoomTypeService. I will simplify your code a bit here. But you didn't show the relevant parts there anyway:
public interface IRoomTypeRepository
{
    void Save(RoomType roomType);
}

public class RoomTypeService
{
    private readonly IRoomTypeRepository _repository;

    public RoomTypeService(IRoomTypeRepository repository)
    {
        _repository = repository;
    }

    public void CreateRoomType(RoomType roomType)
    {
        _repository.Save(roomType);
    }
}



为了测试我们需要提供存储库实例的方法。这当然是模拟,你自己已经想到了很多。现在想想你想要达到的目标,你的测试的目标是什么?我们需要检查roomType实例是否已保存到存储库中。我们需要以这样的方式准备模拟,以便我们可以验证这是否已完成。我喜欢用以下格式编写测试:


In order to test the method we need to supply the repository instance. This will be the mock of course, you figured that much by yourself already. Now think of what are you trying to achieve, what's the objective of your test? We need to check that the roomType instance get's saved to the repository. We need to prepare the mock in such way that we can verify this was done. I like to write my test in following format:

[TestMethod]
public void CreateRoomType()
{
    // arrange
    var repository = MockRepository.GenerateMock<IRoomTypeRepository>();
    var roomType = new RoomType();
    repository.Expect(x => x.Save(roomType));
    var service = new RoomTypeService(repository);

    // act
    service.CreateRoomType(roomType);

    // assert
    repository.VerifyAllExpectations();
}



注意存储库上的Expect方法调用。这样我们就让rhino mocks知道我们要检查对Save()方法的调用(具有roomType的确切实例)。然后,我们在存储库mock上调用VerifyAllExpectations()时最终评估这个期望。现在尝试在服务类中注释掉对_repository.Save()的调用 - 测试应该失败。



这当然是微不足道的。但是想象一下,服务中有更多的逻辑。通常,您只想一次测试一个功能。这意味着限制期望并使用存根来进行其他方法调用。如果你在任何地方使用期望,你的测试将与测试类的内部结构紧密耦合,因此容易破坏并且难以维护。根据我的经验,当你嘲笑工作单元时尤其如此。


Note the Expect method call on the repository. This way we let rhino mocks know we want to check the call to the Save() method (with the exact instance of roomType). We then evaluate this expectations at the end when calling VerifyAllExpectations() on the repository mock. Now try to comment out the call to _repository.Save() in the service class - the test should fail.

This is of course trivial. But imagine there is a lot more logic in the service. Generally you only want to test one functionality at a time. This means limiting the expectations and using stubs for other method calls. If you'd use expectations everywhere your test would be too tightly coupled to the internals of the tested class hence easy to break and hard to maintain. In my experience this is especially true when you are mocking unit of work.


这篇关于使用Rhino mock进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆