C# 模仿用户主体

C# 模仿用户主体,c#,.net,tdd,C#,.net,Tdd,我有一个类处理exchange邮箱的密码更改和过期检查。 我在UserPrincipal上检查LastPasswordSet 那么TDD呢 我想通过编写一些测试来检查我的类是否正确处理了密码检查。但是我无法理解我如何能够嘲笑UserPrincipal.FindByIdentity(principalContext,[some username]) 我将要编写一个方法,如果在过去90天内更改了密码,该方法将返回true/false。所以我想模拟UserPrincipal,这样我就可以在测试中设置L

我有一个类处理exchange邮箱的密码更改和过期检查。 我在UserPrincipal上检查LastPasswordSet

那么TDD呢

我想通过编写一些测试来检查我的类是否正确处理了密码检查。但是我无法理解我如何能够嘲笑UserPrincipal.FindByIdentity(principalContext,[some username])


我将要编写一个方法,如果在过去90天内更改了密码,该方法将返回true/false。所以我想模拟UserPrincipal,这样我就可以在测试中设置LastPasswordSet返回值,只是为了检查我将要为“密码需要更改通知”编写的逻辑。

恐怕UserPrincipal类不是真正的TDD友好类。

把你需要的功能包装到你的类中,然后模仿它怎么样?

我将用一个简洁的短语来回答这个问题

“不要嘲笑你没有的类型” 找不到权威的博客帖子来支持。虽然这似乎是乔·沃恩斯的功劳

如果我记得的话,UserPrincipal是一个与身份验证相关的.Net framework类。无法控制(可以更改)的模拟类型可能会导致脆弱的测试

相反,从UserPrincipal中发现您的设计想要什么

  • 查找UserPrincipal通过tding客户端间接履行或实现的角色
  • 在单元测试中模拟该角色并测试所有调用者
  • 进行“集成测试”,以确保您的实际实现在调用UserPrincipal时按正确的按钮
  • 依靠端到端/验收测试来发现所有组件串在一起时出现的错误

我意识到这是一篇老文章,但最近我遇到了与原始海报相同的问题,在阅读了答案后,我想我必须做同样的事情。我不希望其他人读到这篇文章,像我一样浪费宝贵的时间,所以我决定真正回答这篇文章

在意识到没有简单的方法包装UserPrincipal功能,也没有像建议的那样依赖集成或端到端测试之后,我记得有一种方法可以模拟静态类。话虽如此,下面就是如何使用

private void MockUserPrincipal()
{
//模拟主体上下文
var context=Mock.Create((action)=>action.MockConstructor());
//模拟用户主体
var user=Mock.Create(()=>newuserprincipal(context));
//模拟你需要的属性
Mock.Arrange(()=>user.Enabled)。返回(true);
Mock.Arrange(()=>user.UserPrincipalName).Returns(“TestUser”);
Mock.Arrange(()=>user.LastPasswordSet).Returns(DateTime.Now);
//模拟您需要的任何函数
Mock.Arrange(()=>user.IsAccountLockedOut()).Returns(false);
//设置静态UserPrincipal类
Mock.SetupStatic();
//模拟所需的静态函数
Mock.Arrange(()=>UserPrincipal.FindByIdentity(Arg.IsAny(),Arg.AnyString)).Returns(user);
//现在,使用任何上下文和标识调用UserPrincipal.FindByIdentity将返回模拟的UserPrincipal
}

这篇文章很旧,但有一个有效的例子。即使您永远不应该测试其他人的代码,但您希望测试您的方法。您的方法可能需要来自另一个方法返回的
UserPrincipal
的数据。现在假设您需要检查
LastPasswordSet
属性

  • 右键单击单元测试项目中的.dll
    System.DirectoryServices.AccountManagement
    。选择“添加假货组件”
  • 添加此单元测试

    [TestMethod]
    public async Task ActiveDirectoryUserFactory_CreateUserAsyncAndWhatYouExpect()
    {
        // Arrange
        using(ShimsContext.Create())
        {
            var userPrincipal = new System.DirectoryServices.AccountManagement.Fakes.ShimUserPrincipal();
            var baseUserPrincipal = new System.DirectoryServices.AccountManagement.Fakes.ShimAuthenticablePrincipal(userPrincipal);
    
    
            baseUserPrincipal.LastPasswordSetGet = () => DateTime.Now;
    
            // Mock the returned UserPrincipal to use our userPrincipal, here's for Moq
            _class.Setup(x => x.GetUserAsync("param"))
                .Returns(Task.FromResult<UserPrincipal>(userPrincipal));
    
    
            // Act, your method that gets your shimUserPrincipal from _class.GetUserAsync in your _target class (I understood you got the UserPrincipal from external source)
            var user = await _target.YourMethod();
    
            // Assert
            Assert.IsNull(user);
        }
    
    }
    
    // method that does the code you want to test
    public async Task<Object> YourMethod()
    {
        var user = await _class.GetUserAsync("param");
        var lastLogin = user.LastPasswordSet;
        return new Object()
    }
    
    [TestMethod]
    公共异步任务ActiveDirectoryUserFactory\u CreateUserAsyncAndWhatYouExpect()
    {
    //安排
    使用(ShimsContext.Create())
    {
    var userPrincipal=new System.DirectoryServices.AccountManagement.Fakes.ShimUserPrincipal();
    var baseUserPrincipal=new System.DirectoryServices.AccountManagement.Fakes.ShimAuthenticatablePrincipal(userPrincipal);
    baseUserPrincipal.LastPasswordSetGet=()=>DateTime.Now;
    //模拟返回的UserPrincipal以使用我们的UserPrincipal,这里是Moq
    _Setup(x=>x.GetUserAsync(“param”))
    .Returns(Task.FromResult(userPrincipal));
    //Act,从_目标类中的_class.GetUserAsync获取shimUserPrincipal的方法(我知道您是从外部源获取UserPrincipal的)
    var user=wait_target.YourMethod();
    //断言
    Assert.IsNull(用户);
    }
    }
    //方法,该方法执行要测试的代码
    公共异步任务方法()
    {
    var user=await_class.GetUserAsync(“param”);
    var lastLogin=user.LastPasswordSet;
    返回新对象()
    }
    

  • 垫片有很多来源,所以我就让它变成这样。希望这能帮助那些在谷歌上搜索“mock UserPrincipal”的人。

    是的,我已经考虑过了,最后可能会得到一个userprincipalwrapperHelper提示:-)您需要Visual Studio Enterprise edition来启用文档中所述的假程序集:
    [TestMethod]
    public async Task ActiveDirectoryUserFactory_CreateUserAsyncAndWhatYouExpect()
    {
        // Arrange
        using(ShimsContext.Create())
        {
            var userPrincipal = new System.DirectoryServices.AccountManagement.Fakes.ShimUserPrincipal();
            var baseUserPrincipal = new System.DirectoryServices.AccountManagement.Fakes.ShimAuthenticablePrincipal(userPrincipal);
    
    
            baseUserPrincipal.LastPasswordSetGet = () => DateTime.Now;
    
            // Mock the returned UserPrincipal to use our userPrincipal, here's for Moq
            _class.Setup(x => x.GetUserAsync("param"))
                .Returns(Task.FromResult<UserPrincipal>(userPrincipal));
    
    
            // Act, your method that gets your shimUserPrincipal from _class.GetUserAsync in your _target class (I understood you got the UserPrincipal from external source)
            var user = await _target.YourMethod();
    
            // Assert
            Assert.IsNull(user);
        }
    
    }
    
    // method that does the code you want to test
    public async Task<Object> YourMethod()
    {
        var user = await _class.GetUserAsync("param");
        var lastLogin = user.LastPasswordSet;
        return new Object()
    }