使用 Moq 模拟方法时如何验证方法参数的属性值是否已设置?

发布于 2024-08-12 17:47:31 字数 1231 浏览 7 评论 0原文

不确定以前是否有人问过,这里是问题。

代码优先:

    public class Customer {
        public string Password { get; set; }
        public string PasswordHash { get; set; }
    }
    public class CustomerService {
        private ICustomerRepository _repo;

        public CustomerService(ICustomerRepository repo) {
            _repo = repo;
        }

        public int? AddCustomer(Customer customer) {
            customer.PasswordHash = SHA1Hasher.ComputeHash(customer.Password);
            return _repo.Add(customer);
        }
    }

    public interface ICustomerRepository {
        int? Add(Customer c);
    }
    public class CustomerRepository : ICustomerRepository {
        int? AddCustomer(Customer customer) {
            // call db and return identity
            return 1;
        }
    }

    [TestClass]
    public class CustomerServiceTest {
        [TestMethod]
        public void Add_Should_Compute_Password_Hash_Before_Saving() {
            var repoMock = new Mock<ICustomerRepository>();
            //how do I make sure the password hash was calculated before       passing the customer to repository???
        }
    }

如何在将客户传递到存储库之前验证 CustomerService 是否分配了 PasswordHash?

Not sure if it has been asked before, here is the question.

Code first:

    public class Customer {
        public string Password { get; set; }
        public string PasswordHash { get; set; }
    }
    public class CustomerService {
        private ICustomerRepository _repo;

        public CustomerService(ICustomerRepository repo) {
            _repo = repo;
        }

        public int? AddCustomer(Customer customer) {
            customer.PasswordHash = SHA1Hasher.ComputeHash(customer.Password);
            return _repo.Add(customer);
        }
    }

    public interface ICustomerRepository {
        int? Add(Customer c);
    }
    public class CustomerRepository : ICustomerRepository {
        int? AddCustomer(Customer customer) {
            // call db and return identity
            return 1;
        }
    }

    [TestClass]
    public class CustomerServiceTest {
        [TestMethod]
        public void Add_Should_Compute_Password_Hash_Before_Saving() {
            var repoMock = new Mock<ICustomerRepository>();
            //how do I make sure the password hash was calculated before       passing the customer to repository???
        }
    }

How do I verify that CustomerService assigned the PasswordHash before passing the customer to repository?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挽手叙旧 2024-08-19 17:47:31

您可以采取多种方法。虽然这不一定是最好的解决方案,但这是一个不需要您更改现有 API 的解决方案。它假设 SHA1Hasher.ComputeHash 是公共方法。

[TestClass]
public class CustomerServiceTest
{
    [TestMethod]
    public void Add_Should_Compute_Password_Hash_Before_Saving()
    {
        var customer = new Customer { Password = "Foo" };
        var expectedHash = SHA1Hasher.ComputeHash(customer.Password);

        var repoMock = new Mock<ICustomerRepository>();
        repoMock
            .Setup(r => r.Add(It.Is<Customer>(c => c.PasswordHash == expectedHash)))
            .Returns(1)
            .Verifiable();

        // invoke service with customer and repoMock.Object here...

        repoMock.Verify();
    }
}

一个稍微好一点的解决方案是将 SHA1Hasher 转换为注入服务(例如 IHasher),以便您可以确认 PasswordHash 属性已分配由 IHasher 实例创建的值。

进一步开放您的 API,您可以将 PasswordHash 属性设为虚拟,以便您可以将 Mock Customer 传递给 AddCustomer 方法来验证该属性是否已正确设置。

There are several approaches you could take. Although not necessarily the best solution, here's one that doesn't require you to change your existing API. It assumes that SHA1Hasher.ComputeHash is a public method.

[TestClass]
public class CustomerServiceTest
{
    [TestMethod]
    public void Add_Should_Compute_Password_Hash_Before_Saving()
    {
        var customer = new Customer { Password = "Foo" };
        var expectedHash = SHA1Hasher.ComputeHash(customer.Password);

        var repoMock = new Mock<ICustomerRepository>();
        repoMock
            .Setup(r => r.Add(It.Is<Customer>(c => c.PasswordHash == expectedHash)))
            .Returns(1)
            .Verifiable();

        // invoke service with customer and repoMock.Object here...

        repoMock.Verify();
    }
}

A slightly better solution would be to turn the SHA1Hasher into an injected service (such as IHasher) so that you can confirm that the PasswordHash property was assigned the value created by the IHasher instance.

Opening op your API even more, you could make the PasswordHash property virtual, so that you could pass a Mock Customer to the AddCustomer method to verify that the property was correctly set.

清欢 2024-08-19 17:47:31

您可以使 SHA1Hasher 成为非静态和虚拟的,或者将其包装在 ISHA1Hasher 接口中,然后可以对其进行模拟。将静态方法和对象包装在可模拟类中是提高可测试性的经典方法。

You could make SHA1Hasher non-static and virtual or wrap it in a ISHA1Hasher interface which can then be mocked. Wrapping static methods and objects in mockable classes is a classic way to increase testability.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文