DIl*_*d K 8 c# performance unit-testing
我正在尝试创建单元测试.我有班级用户:
public class User
{
public int UsersCount
{
get
{
using (MainContext context = new MainContext())
{
return context.Users.Count();
}
}
}
public Guid Id { get; set; } = Guid.NewGuid();
public string UserName { get; set; }
public string Password { get; set; }
public Contact UserContact { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我的第一个测试是UsersCount_Test测试,它测试UsersCount属性:
[TestMethod]
public void UsersCount_Test()
{
var user = new User();
var context = new MainContext();
int usersCount = context.Users.Count();
context.Users.Add(new User());
context.SaveChanges();
Assert.AreEqual(usersCount + 1, user.UsersCount, $"It should be {usersCount + 1} because we're adding one more user");
}
Run Code Online (Sandbox Code Playgroud)
如果我在我的测试类中添加新的测试方法(我使用单独的类来测试每个实体),我需要创建User的新实例.这就是我这样做的原因:
public class BaseTest<T>
{
public T TestEntity;
public MainContext TestContext = new MainContext();
}
Run Code Online (Sandbox Code Playgroud)
现在每个测试类都继承自这个类.我还创建了测试初始化方法.现在我的测试类看起来像这样:
[TestClass]
public class UserTest : BaseTest<User>
{
[TestMethod]
public void UsersCount()
{
int usersCount = TestContext.Users.Count();
TestContext.Users.Add(new User());
TestContext.SaveChanges();
Assert.AreEqual(usersCount + 1, TestEntity.UsersCount, $"It should be {usersCount + 1} because we're adding one more user");
}
[TestInitialize]
public void SetTestEntity()
{
TestEntity = new User();
}
}
Run Code Online (Sandbox Code Playgroud)
现在我正在向User添加新属性并编写一些逻辑:
string phoneNumber;
public string PhoneNumber { get { return phoneNumber; } set { SetUserContact(phoneNumber, value); phoneNumber = value; } }
void SetUserContact(string oldContact, string newContact)
{
UserContact.ContactsList.Remove(oldContact);
UserContact.ContactsList.Add(newContact);
}
Run Code Online (Sandbox Code Playgroud)
之后,我正在创建新的测试:
[TestMethod]
public void ContactList_Test()
{
var newPhone = "+8888888888888";
TestEntity.PhoneNumber = newPhone;
Assert.IsTrue(TestEntity.UserContact.ContactsList.Any(a => a == newPhone), $"It should contains {newPhone}");
}
Run Code Online (Sandbox Code Playgroud)
测试失败,因为TestEntity的UserContact为null.我知道TestEntity应该由逻辑创建.之后我修复了测试initilizer方法:
[TestInitialize]
public void SetTestEntity()
{
TestEntity = new User() { UserContact = new Contact() };
}
Run Code Online (Sandbox Code Playgroud)
这是联系模式
public class Contact
{
public Guid Id { get; set; } = Guid.NewGuid();
public virtual List<string> ContactsList { get; set; } = new List<string>();
}
Run Code Online (Sandbox Code Playgroud)
我的问题是如何只设置TestEntity一次,是否可能(可能在内存中使用它并在调用SetTestEntity方法时使用它)?因为SetTestentity方法在每个测试中创建一个新实体,所以需要更多的开发时间.(例如,如果创建UserContact实例全部需要3秒,则测试运行时间超过3秒).在这种情况下,另一种方法是在ContactLists测试中设置UserContact,但我认为这不是一个好主意.在将来我们将添加新逻辑时,我需要修复每个测试.请给我任何建议和/或想法.
如果您真的必须TestInitialize
在每次测试之前运行。您只能使用ClassInitialize
一次为类运行测试初始化。
但
从我所看到的,您的性能问题是由您的应用程序的设计和架构引起的,您违反了单一责任原则。创建静态数据库实体或在测试中共享它不是解决方案,它只会产生更多的技术债务。一旦你在测试中共享任何东西,它就必须在测试中维护,并且根据定义,单元测试应该单独和独立运行,以允许使用新数据测试每个场景。
您不应该创建依赖于MainContext
. 单User
真的应该知道Users
数据库里有多少吗?如果没有,请创建单独的存储库,通过添加少数用户调用特定实现并检查是否添加了正确的用户数量,使用 InMemoryDatabaseMainContext
注入和方法GetUsersCount()
和单元测试,如下所示:
public interface IUsersRepository
{
int GetUsersCount();
}
public class UsersRepository : IUsersRepository
{
private readonly EntityFrameworkContext _context;
public UsersRepository(EntityFrameworkContext context)
{
_context = context;
}
public int GetUsersCount()
{
return _context.Users.Count();
}
}
Run Code Online (Sandbox Code Playgroud)
以后只有真正使用上下文的方法才应该被测试,InMemoryDatabase
对于使用 IUserRepository 的方法,每个特定的方法都应该被模拟,因为它是单独测试的。
归档时间: |
|
查看次数: |
298 次 |
最近记录: |