在单元测试中伪造我的数据库层的方法是什么?

Mic*_*hel 5 .net database testing asp.net-mvc unit-testing

我对单元测试有疑问.

假设我有一个带有一个create方法的控制器,它将新客户放入数据库中:

//code a bit shortened
public actionresult Create(Formcollection formcollection){
    client c = nwe client();
    c.Name = formcollection["name"];
    ClientService.Save(c);
{
Run Code Online (Sandbox Code Playgroud)

Clientservice将调用datalayer对象并将其保存在数据库中.

我现在所做的是创建一个数据库测试脚本,并在测试之前将我的数据库设置为已知状态.所以当我在单元测试中测试这个方法时,我知道数据库中必须有一个客户端,它的名字是什么.简而言之:

ClientController cc = new ClientController();
cc.Create(new FormCollection (){name="John"});
//i know i had 10 clients before
assert.areEqual(11, ClientService.GetNumberOfClients());
//the last inserted one is John
assert.areEqual("John", ClientService.GetAllClients()[10].Name);
Run Code Online (Sandbox Code Playgroud)

所以我读过单元测试不应该打到数据库,我已经为数据库类设置了一个IOC,但那又是什么?我可以创建一个假的数据库类,并使它什么都不做.

但是当然我的断言不起作用,因为如果我说它GetNumberOfClients()总是返回X,因为它与Create Method中使用的假数据库类没有交互.

我还可以在假数据库类中创建一个客户端列表,但由于将创建两个不同的实例(一个在控制器操作中,一个在单元测试中),它们将没有交互.

如果没有数据库,这个单元测试工作的方法是什么?

编辑:客户端服务不直接连接到数据库.它调用ClientDataClass,它将连接到数据库.因此ClientDatabaseClass将被替换为假的

Yau*_*kha 5

在这种特殊情况下,您将独立于数据库测试控制器.ClientService是对数据库的抽象,应该由test double替换.你将假注入控制器,但仍然断言真正的实现.这毫无意义.

断言注入控制器的同一个对象.

 interface IClientService 
    {
      public void GetNumberOfClients();
      public IList<Client> GetAllClients();
      public void Insert(Client client);
    }
Run Code Online (Sandbox Code Playgroud)

假服务实施:

   class FakeClientService : IClientService
   {
     private IList<CLient> rows = new List<CLient>();

     public void GetNumberOfClients()
     { 
       return list.Count;
     }

     public IList<Client> GetAllClients()
     {
       return list;
     }

     public void Insert(Client client)
     {
       client.Add(client);
     }
   }
Run Code Online (Sandbox Code Playgroud)

测试:

[Test]
public void ClientIsInserted()
{
  ClientController cc = new ClientController();
  FakeClientService fakeService = new FakeClientService();

  cc.ClientService = fakeService;

  cc.Create(new FormCollection (){name="John"});

  assert.areEqual(1, fakeService.GetNumberOfClients());
  assert.areEqual("John", fakeService.GetAllClients()[0].Name);
}
Run Code Online (Sandbox Code Playgroud)

如果要检查控制器和服务如何协同工作 - 为ClientDatabaseClass创建假.这将是:

[Test]
public void ClientIsInserted()
{
  ClientController cc = new ClientController();
  IClientDatabaseClass databaseFake = new ClientDatabaseClassFake();

  ClientService service= new ClientService();

  service.Database = databaseFake;
  cc.ClientService = service;

  cc.Create(new FormCollection (){name="John"});

  assert.areEqual(1, service.GetNumberOfClients());
  assert.areEqual("John", service.GetAllClients()[0].Name);
}
Run Code Online (Sandbox Code Playgroud)