c#:为此用例编写测试

时间:2011-11-26 12:05:26

标签: unit-testing c#-3.0 nunit moq

我想检查用户密码是否已更改,编写此测试的最佳方法是什么?我的代码是否需要重构,因为它错了?

代码内部password.ResetUserPassword - 我找出哪个用户请求更改密码,是否可以更改,如果需要则生成电子邮件...我是否需要传入User个对象这种方法?这个逻辑由我的控制器(或后端,如果需要)调用

    [Test]
    public void Test_If_New_Password_Is_Generated_For_User()
    {
        var repo = new ReadOnlySession();
        var update = new UpdateSession();

        var passwordService = new UserPasswordService();
        var password = new AccountProfileProcessor(repo, update, passwordService);

        password.ResetUserPassword("companyid", "jon.smithers", null);

        Assert.Pass();

    }

//我正在调用的方法

_ passwordService是一种处理为用户生成新密钥的服务

    public void ResetUserPassword(string identifier, string loginid, string passwordreseturl)
    {
        //get user object
        var currentUser = _readOnlySession.All<User>()
            .Where(x => x.Login == loginid)
            .SingleOrDefault(); //any other logic to get user resides here...

        if (currentUser == null)
            throw new UserNotFoundException();

        _passwordService.ResetPassword(currentUser.User, identifier, loginid);

        //persist data
        _updateSession.Update(currentUser.User);

        //send out email with the url as a link inside the email
    }

1 个答案:

答案 0 :(得分:1)

以下内容可行。 (我不得不对你的类做一些假设,我仍然不确定currentUser.User是什么类型的。)

模拟和解耦的技巧是制作所有服务依赖接口。

您需要另一个接口依赖项(带有关联的模拟和验证)才能发送邮件。您可能希望将所有这些放在一个单独的测试夹具中,安排在设置中,然后在单独的测试方法中验证每个服务调用。

对我而言,这种方法做得太多了 - 它有多重责任。痛苦的测试设置和多次验证都是代码味道。考虑将其分解为更小的方法(可能仍然从现有方法调用),然后独立地测试它们。 GetUser(loginId)(或抛出)将是我提取的第一种方法。将其中一些方法移到服务(例如存储库)上会使这更容易测试。

澄清 - 您在评论中提到要检查PasswordKey是否不同。这是具体UserPasswordService的责任。你需要独立测试。

// Arrange

const string TestLogin = "jon.smithers";
User testUser = new User { Login = TestLogin };
var testUsers = new List<User> { testUser };

var mockUpdate = new Mock<IUpdateSession>();

var mockRepo = new Mock<IReadOnlySession>();
mockRepo.Setup(x => x.All<User>()).Returns(testUsers);

var mockPasswordService = new Mock<IUserPasswordService>();

var password = new AccountProfileProcessor(
    mockRepo.Object, mockUpdate.Object, mockPasswordService.Object);

// Act

password.ResetUserPassword("companyid", TestLogin, null);

// Assert

mockPasswordService.Verify(
    x => x.ResetPassword(
        It.IsAny<string>(), It.IsAny<string>(), TestLogin));

mockUpdate.Verify(x => x.Update(testUser));