我正在尝试创建单元测试。我有类(class)用户:

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

我的第一个测试是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");
    }

如果我在测试类中添加了新的测试方法(我正在使用单独的类来测试每个实体),则需要创建User的新实例。这就是为什么我这样做:
    public class BaseTest<T>
{
    public T TestEntity;

    public MainContext TestContext = new MainContext();
}

现在,每个测试类都从该类继承。而且我还创建了测试初始化​​方法。现在我的测试类如下所示:
 [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();
    }
}

现在,我向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);
    }

之后,我要创建新的测试:
     [TestMethod]
    public void ContactList_Test()
    {
        var newPhone = "+8888888888888";
        TestEntity.PhoneNumber = newPhone;
        Assert.IsTrue(TestEntity.UserContact.ContactsList.Any(a => a == newPhone), $"It should contains {newPhone}");
    }

测试失败,因为TestEntity的UserContact为空。我知道TestEntity应该由逻辑创建。之后,我修复测试初始化​​器方法:
 [TestInitialize]
    public void SetTestEntity()
    {
        TestEntity = new User() { UserContact = new Contact() };
    }

这是联系方式
    public class Contact
{
    public Guid Id { get; set; } = Guid.NewGuid();
    public virtual List<string> ContactsList { get; set; } = new List<string>();
}

我的问题是如何只设置一次TestEntity,这有可能吗(也许将其保存在内存中并在调用SetTestEntity方法时使用它)?因为SetTestentity方法在每个测试中都会创建一个新实体,所以需要花费更多的开发时间。 (例如,如果创建UserContact实例全部花费3秒钟,则测试运行超过3秒钟)。在这种情况下,另一种方法是在ContactLists测试中设置UserContact,但是我认为这不是一个好主意。将来,当我们将添加新的逻辑时,我需要修复每个测试。请给我任何建议和/或想法。

最佳答案

如果您真的必须在每次测试之前运行TestInitialize。您可以使用ClassInitialize对类仅运行一次测试初始化​​。



从我的角度来看,您的性能问题是由您的应用程序的设计和架构破坏了您的工作范围而又违反了单一职责原则。创建静态数据库实体或在测试中共享它不是一个解决方案,它只会增加技术负担。一旦您在整个测试中共享任何内容,就必须对其进行维护,并按定义进行单元测试应该分别独立运行,以允许使用新数据测试每个场景。

您不应该创建依赖于MainContext的数据库模型。单个User是否应该真正知道数据库中有多少个Users?如果没有,请创建单独的存储库,该存储库将注入(inject)MainContext和方法GetUsersCount(),并通过添加一些调用特定实现的用户并检查是否添加了正确的用户数来使用InMemoryDatabase对该单元进行测试。

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

以后,只有真正使用上下文的方法才应该使用InMemoryDatabase进行测试,而对于使用IUserRepository的方法,应该对每个特定的方法进行模拟,因为它们是分开进行测试的。

关于c# - 如何使测试在内存中初始化并在每个测试中使用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54643532/

10-11 22:24
查看更多