单位测试应在失败时通过



任何人都可以在下面的示例中看到我出错的地方。我正在编写测试以检查是否已经存在IF。我有一个"用户服务",可以在通用存储库中调用方法为" rentalsRepository",该方法为我呼叫数据。*请注意,该代码在系统中起作用,只是在我的测试中不在

repo

public class RentalsRepository<T> : IRentalsRepository<T> where T : BaseClass
{
    private readonly RentalsDBContext _Context;
    private DbSet<T> entities;
    string errorMessage = string.Empty;
    public RentalsRepository(RentalsDBContext _Context)
    {
        this._Context = _Context;
        entities = _Context.Set<T>();
    }
    public T Get(string Id)
    {
        return entities.SingleOrDefault(e => e.Id == Id);
    } ...

uservice

 public class UserService : IUserService {
private IRentalsRepository<UserAccount> _userRepository;
    public UserService(IRentalsRepository<UserAccount> userRepository)
    {
        this._userRepository = userRepository;
    }
    public UserAccount GetUserFromId(string id)
    {
        UserAccount user = _userRepository.Get(id);
        user.Email = Encryption.DecryptFromDatabase(user.Email);
        return user;
    }...

测试类

  [Fact]
    public void UserService_GetByID()
    {
        var users = new List<UserAccount> {
            new UserAccount { Id = "idstring1", Username = "username1"},
            new UserAccount { Id = "idstring2", Username = "username2" },
            new UserAccount { Id = "idstring3", Username = "username3" },
    }.AsQueryable();
        var mockSet = new Mock<DbSet<UserAccount>>();
        mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Provider).Returns(users.Provider);
        mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Expression).Returns(users.Expression);
        mockSet.As<IQueryable<UserAccount>>().Setup(m => m.ElementType).Returns(users.ElementType);
        mockSet.As<IQueryable<UserAccount>>().Setup(m => m.GetEnumerator()).Returns(users.GetEnumerator());
        var mockContext = new Mock<RentalsDBContext>();
        mockContext.Setup(m => m.Set<UserAccount>()).Returns(mockSet.Object);
        var mockRepo = new Mock<IRentalsRepository<UserAccount>>();
        mockRepo.Setup(m => m.Get(It.IsAny<string>())).Returns(mockSet.Object.FirstOrDefault());
        var service = new UserService(mockRepo.Object);
        UserAccount results = service.GetUserFromId("non-existant");
        Assert.Equal("idstring1", results.Id);
    } 

当我调试时,我可以在方法public UserAccount GetUserFromId(string id)中看到"不存在"的值',但它仍然以某种方式返回用户

最新尝试

        [Fact]
    public void UserService_GetUserByUsername()
    {
        byte[] b = Encryption.GetSalt();
        var users = new List<UserAccount> {
            new UserAccount { Id = "idstring2", Username = "username2" },
           new UserAccount { Id = "idstring3", Username = "username3" },
    }.AsQueryable();
        var mockContext = new Mock<RentalsDBContext>();
        var mockSet = new Mock<DbSet<UserAccount>>();
        mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Provider).Returns(users.Provider);
        mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Expression).Returns(users.Expression);
        mockSet.As<IQueryable<UserAccount>>().Setup(m => m.ElementType).Returns(users.ElementType);
        mockSet.As<IQueryable<UserAccount>>().Setup(m => m.GetEnumerator()).Returns(users.GetEnumerator());
        mockContext.Setup(m => m.Set<UserAccount>()).Returns(mockSet.Object);
        var mockRepo = new Mock<RentalsRepository<UserAccount>>(mockContext.Object);
        var testClass = new UserService(mockRepo.Object);
        UserAccount results = testClass.GetUserByUsername("username2");
        Assert.Equal("username1", results.Username);
    }
mockRepo.Setup(m => m.Get(It.IsAny<string>())).Returns(mockSet.Object.FirstOrDefault());

无论您将哪种字符串传递到Get()中,都将返回模拟集中的第一个记录(" IDString1"(。假设您正确地将模拟的DB上下文放入存储库中,没有理由模拟Get()

说,如果您要测试是否已经存在ID,那是存储库的函数,而不是您的服务。您的服务所做的就是解密电子邮件。您正在以这种方式测试存储库和服务,这不是单位测试。

编辑

我们回到了您要测试的问题的问题。如果要测试存储库会检索正确的用户帐户,则将模拟DB上下文并使用真实的存储库类。

[Fact]
public void UserRepository_Get()
{
    var users = new List<UserAccount> {
        new UserAccount { Id = "idstring2", Username = "username2" },
       new UserAccount { Id = "idstring3", Username = "username3" },
    }.AsQueryable();
    var mockSet = new Mock<DbSet<UserAccount>>();
    mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Provider).Returns(users.Provider);
    mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Expression).Returns(users.Expression);
    mockSet.As<IQueryable<UserAccount>>().Setup(m => m.ElementType).Returns(users.ElementType);
    mockSet.As<IQueryable<UserAccount>>().Setup(m => m.GetEnumerator()).Returns(users.GetEnumerator());
    var mockContext = new Mock<RentalsDBContext>();
    mockContext.Setup(m => m.Set<UserAccount>()).Returns(mockSet.Object);
    var testClass = new RentalsRepository<userAccount>(mockContext.Object);
    var results = testClass.Get("username2");
    Assert.Equal("username2", results.Username);
}

如果要测试用户服务检索用户并解密电子邮件,则将模拟存储库(并且是Get函数(并使用真实的服务类。

[Fact]
public void UserService_GetUserByUsername()
{
    var userAccount = new UserAccount { Id = "idstring2", Username = "username2", Email = "" };
    var mockRepo = new Mock<IRentalsRepository<UserAccount>>();
    mockRepo.Setup(m => m.Get("idstring2").Returns(userAccount);
    var testClass = new UserService(mockRepo.Object);
    var results = testClass.GetUserByUsername("idstring2");
    Assert.Equal("idstring2", results.Username);
    Assert.AreEqual("???", results.Email);
}

如果您想一起测试存储库和服务,那么您当然可以,但是这不是单位测试,因为您一次测试了两件事。在这种情况下,您模拟了DB上下文并使用真实的存储库和服务类。

[Fact]
public void UserRepository_Get()
{
    var users = new List<UserAccount> {
        new UserAccount { Id = "idstring2", Username = "username2" },
       new UserAccount { Id = "idstring3", Username = "username3" },
    }.AsQueryable();
    var mockSet = new Mock<DbSet<UserAccount>>();
    mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Provider).Returns(users.Provider);
    mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Expression).Returns(users.Expression);
    mockSet.As<IQueryable<UserAccount>>().Setup(m => m.ElementType).Returns(users.ElementType);
    mockSet.As<IQueryable<UserAccount>>().Setup(m => m.GetEnumerator()).Returns(users.GetEnumerator());
    var mockContext = new Mock<RentalsDBContext>();
    mockContext.Setup(m => m.Set<UserAccount>()).Returns(mockSet.Object);
    var repository = new RentalsRepository<userAccount>(mockContext.Object);
    var service = new UserService(repository);
    var results = service.GetUserByUsername("username2");
    Assert.Equal("username2", results.Username);
}