gpt4 book ai didi

c# - 工作单元测试的单元测试失败

转载 作者:行者123 更新时间:2023-12-02 21:49:56 25 4
gpt4 key购买 nike

这是我的测试:

[TestMethod]
public void TestUnitOfWork()
{
UnitOfWork unitOfWork = new UnitOfWork();

unitOfWork.ContactRepository.Insert(new Contact
{
Id = Guid.NewGuid(),
FirstName = "Dom",
LastName = "A",
Email = "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="90f4fffdf9fef9f3f1e2f3f8e5f1fcd0e9f1f8ffffbef3fffd" rel="noreferrer noopener nofollow">[email protected]</a>"
});

var contacts = unitOfWork.ContactRepository.Get(x => x.FirstName == "Dominic");

Assert.AreEqual(1, contacts.Count());
}

我得到的错误是:

Test method MvcContacts.Tests.Controllers.HomeControllerTest.TestUnitOfWork threw exception: System.Data.ProviderIncompatibleException: An error occurred while getting provider information from the database. This can be caused by Entity Framework using an incorrect connection string. Check the inner exceptions for details and ensure that the connection string is correct. ---> System.Data.ProviderIncompatibleException: The provider did not return a ProviderManifestToken string. ---> System.Data.SqlClient.SqlException: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)

我没有设置任何数据库;即我的上下文如下所示:

namespace MvcContacts.DAL
{
public class ContactsContext : DbContext
{
public DbSet<Contact> Contacts { get; set; }
}
}

我不知道如何将其映射到我的数据库;但是,我想我还不必这样做,因为我只是尝试使用模拟数据进行测试。我错了吗?

E1:这是我的工作单元类(class)。

namespace MvcContacts.DAL
{
public class UnitOfWork : IDisposable
{
private ContactsContext context = new ContactsContext();
private GenericRepository<Contact> contactRepository;

public GenericRepository<Contact> ContactRepository
{
get
{
if (this.contactRepository == null)
{
this.contactRepository = new GenericRepository<Contact>(context);
}
return contactRepository;
}
}

public void Save()
{
context.SaveChanges();
}

private bool disposed = false;

protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

最佳答案

正如我所说,问题是您实际上是在 UnitOfWork 内调用真正的数据库。 。我很确定,你的GenericRepository<>类刚刚结束 DbSet在你的上下文中。您可以在此处创建“真正的”数据库访问器。

private ContactsContext context = new ContactsContext();

但问题是您误解了存储库的整个概念。工作单元是某些数据源的抽象。您不应该对抽象进行单元测试,而应该对依赖于它的某些功能进行单元测试。顺便说一句,DbContext根据该定义,它本身就是一个工作单元(来自 martinfowler.com):

Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.

为什么人们不保持原样呢?因为它有一个缺陷。让我通过例子来解释一下。看起来您正在学习 ASP.Net MVC,所以让我们编写一些 Controller :

public class ContactsController
{
public ActionResult Index(int pageSize, int currentPage)
{
using(var db = new MvcLearningContext())
{
var contacts = db.Contacts
.Skip((currentPage - 1) * pageSize)
.Take(pageSize)
.ToList();
return View(contacts);
}
}
}

正如您所知,MVC 的一大优势是能够对 Controller 逻辑进行单元测试。因此,让我们尝试编写一个简单的单元测试,以确保 Controller 操作不会返回比给定页面大小更多的条目:

[TestMethod]
public void IndexShouldNotReturnMoreThanPageSizeResults()
{
// arrange
var controller = new ContactsController();

// act
var view = (ViewResult) controller.Index(10, 1);

// assert
var Model = (IEnumerable<Contact>) view.Model;
Assert.IsTrue(view.Model.Count() <= 10)
}

但是等等...我们不想想要在单元测试中查询真实的数据库。 EF的DbContext的问题来了:这完全取决于真实的数据库。但我们怎样才能避免这种情况呢? UnitOfWork发挥作用:

public class ContactsController
{
private UnitOfWorkFactoryBase _factory { get; set; }

public ContactsController(UnitOfWorkFactoryBase factory)
{
factory = _factory;
}

public ActionResult Index(int pageSize, int currentPage)
{
using(var db = _factory.Create())
{
var contacts = db.Contacts
.Skip((currentPage - 1) * pageSize)
.Take(pageSize)
.ToList();
return View(contacts);
}
}
}

单元测试代码:

[TestMethod]
public void IndexShouldNotReturnMoreThanPageSizeResults()
{
// arrange
var factory = new MockUnitOfWorkFactory();
var controller = new ContactsController(factory);

// act
var view = (ViewResult) controller.Index(10, 1);

// assert
var Model = (IEnumerable<Contact>) view.Model;
Assert.IsTrue(view.Model.Count() <= 10)
}

并在生产中替换 MockUnitOfWorkFactoryUnitOfWorkFactory

UPD:工厂的基本实现:

public abstract class UnitOfWorkFactoryBase
{
public abstract UnitOfWorkBase Create();
}

public class UnitOfWorkFactory : UnitOfWorkFactoryBase
{
public override UnitOfWorkBase Create()
{
return new UnitOfWork();
}
}

public class MockUnitOfWorkFactory : UnitOfWorkFactoryBase
{
public override UnitOfWorkBase Create()
{
return new MockUnitOfWork();
}
}

UnitOfWorkMockUnitOfWork是 UnitOfWorkBase 抽象类的实现。

关于c# - 工作单元测试的单元测试失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18852417/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com