简体   繁体   English

单元测试应该通过失败

[英]Unit test is passing when it should fail

Can anyone see where I have went wrong in the following example. 在下面的示例中,谁能看到我哪里出了问题。 I am writing tests to check for an if ID already exists. 我正在编写测试以检查ID是否已存在。 I have a 'UserService' that calls methods in a generic repository 'RentalsRepository' that makes the calls to the data for me. 我有一个“ UserService”,它可以调用通用存储库“ RentalsRepository”中的方法,该方法可以为我进行数据调用。 *Note the code works in the system, just not in my tests *请注意,代码在系统中有效,但在我的测试中无效

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

UserService 用户服务

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

Test Class 测试班

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

When I debug I can see the value '"non-existant"' is being used in the method public UserAccount GetUserFromId(string id) but it still somehow returns a user 当我调试时,我可以看到在方法public UserAccount GetUserFromId(string id)中使用了“不存在”值,但它仍然以某种方式返回了用户

Latest Attempt 最新尝试

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

Is going to return the first record in your mock set ("idstring1") no matter what string you pass into Get() . 无论您将什么字符串传递给Get()都将返回模拟集中的第一条记录(“ idstring1” Get() Assuming you get your mocked db context into your repository correctly, there is no reason to mock Get() at all. 假设您将模拟的db上下文正确地放入存储库中,则完全没有理由模拟Get()

Having said that, if you're trying to test if an ID already exists, that's a function of the repository, not your service. 话虽如此,如果您要测试ID是否已存在,那是存储库的功能,而不是您的服务。 All your service is doing is decrypting the email. 您的所有服务正在解密电子邮件。 You're testing both the repository and the service this way, which is not a unit test. 您正在以这种方式测试存储库和服务,这不是单元测试。

EDIT 编辑

We're back to the question of what you are trying to test. 我们回到了您要测试的问题。 If you want to test that the repository retrieves the correct user account, you would mock the db context and use the real repository class. 如果要测试存储库是否检索了正确的用户帐户,则可以模拟数据库上下文并使用真实的存储库类。

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

If you want to test that the user service retrieves the user and decrypts the email, you would mock the repository (and it's Get function) and use the real service class. 如果要测试用户服务检索用户并解密电子邮件,则可以模拟存储库(它是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);
}

If you want to test both the repository and service together, you certainly can, but it won't be a unit test since you're testing two things at once. 如果您想同时测试存储库和服务,您当然可以,但是由于您一次要测试两件事,所以它不是单元测试。 In that case, you mock the db context and use real repository and service classes. 在这种情况下,您可以模拟数据库上下文并使用真实的存储库和服务类。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当字符串是另一个字符串的选定有序子集时,单元测试应该失败 - Unit test should fail when string is a selected ordered subset of another string 这个单元测试在执行时如何通过? - How is this unit test passing when exercised? 为什么在比较两个双打时这个单元测试失败了? - Why does this unit test fail when comparing two doubles? 单元测试在不应该做的时候失败 - Unit-test fail when it shouldn't do 单元测试未通过,为什么? - Unit Test not passing, why? 单元测试应该失败 - Unit test should be failing 正则表达式-不允许通过分号通过单元测试的字符 - Regular Expressions - Semicolon passing unit test when not allowed character Azure Devops - MSTest - 如果我的单元测试失败,我如何使构建失败,但在集成测试失败时继续(带有警告/通知) - Azure Devops - MSTest - How can I fail a build if my unit tests fail, but continue (with warning/notification) when integration test fail 在单元测试中将guid作为查询传递 - Passing guid as query in unit test 为什么使用HostType(“ Moles”)进行的单元测试中的断言在单独运行时可以通过,而在一组测试中运行时却失败? - Why would an assert on a unit test with HostType(“Moles”) pass when run individually, but fail when run with a group of tests?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM