Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 没有setter的模拟对象_C#_.net_Unit Testing_Moq - Fatal编程技术网

C# 没有setter的模拟对象

C# 没有setter的模拟对象,c#,.net,unit-testing,moq,C#,.net,Unit Testing,Moq,我正在使用一个第三方库UserContext,它只有一堆{get;} public static UserContext Current { get; } public UserContact CurrentContact { get; } public string UserContactName { get; } 在我的代码中,它只是返回CurrentUser,如下所示: void DoSomething(){ UserContext Current = UserContext.C

我正在使用一个第三方库UserContext,它只有一堆{get;}

public static UserContext Current { get; }
public UserContact CurrentContact { get; }
public string UserContactName { get; }
在我的代码中,它只是返回CurrentUser,如下所示:

void DoSomething(){
    UserContext Current = UserContext.Current; // 3rd party lib
}
我没有办法为单元测试设置一个新的伪对象。因此,为了在我的代码中模拟这一点,我做了以下工作:

创建了从UserContext继承并覆盖当前属性的子类:

public class UserContextFake : UserContext
{
    public new UserContext Current { get; set; }
}
然后创建了一个接口和包装器:

public class UserContextWrapper : IUserContext
{
    public UserContextWrapper()
    {
        userContext = UserContext.Current;
    }

    public UserContextWrapper(UserContext context)
    {
        userContext = context;
    }

    private readonly UserContext userContext;

    public UserContext Current
    {
        get { return userContext; }
    }
}
现在我可以将userContextWrapper导入到我的类中。我公开了两个构造函数:一个是使用UserContext.Current(第三方库)会话内容生成代码的构造函数,另一个是可以接收自定义UserContextFake的构造函数。在IoC中,我将IUserContext映射到UserContext


问题:如果CurrentContact不在界面中,而是UserContext(UserContext.CurrentContact)的属性,我如何模拟它?

你不能为整个3dr party library创建一个界面吗?然后实现这个接口并使用这个类作为第三方库的包装器。方法。然后在被测试的类中添加例如可用于注入接口模拟的属性。示例(未经测试)。嗯

公共接口ITIRDPartyLibraryWrapper
{
UserContext当前{get;}
UserContact CurrentContact{get;}
字符串UserContactName{get;}
}
公共类第三方图书馆包装器
:i第三方图书馆包装
{
当前公共用户上下文
{ 
获取{/*从第三方库返回当前值*/}
}
公共用户联系人CurrentContact
{ 
获取{/*从第三方库返回CurrentContact*/}
}
公共字符串UserContactName
{ 
获取{/*从第三方库返回UserContactName*/}
}
}
公共类未测试
{
//注入第三方库
私人图书馆;
公共虚拟iHirdPartyLibraryWrapper库
{
得到
{
如果(_library==null)
_library=新的第三方LibraryWrapper();
归还图书馆;
}
设置
{
if(值!=null)
_图书馆=价值;
}
}
无效剂量测定法(){
UserContext-Current=Library.Current;
}
}
[测试方法]
使用图书馆模拟()时的公共无效数据
{
//安排
UserContext fakeUserContext=新的UserContext();
Mock libraryMock=新建Mock();
libraryMock.Setup(l=>l.Current).Returns(fakeUserContext);
ClassUnderTest cut=新的ClassUnderTest();
cut.Library=libraryMock.Object;
//表演
切割.剂量测定法()
//断言
// ...
}

正确是什么意思?它对您有用吗?这个IUserContext是由第三方库实现的吗?不是。这就是为什么我必须创建一个包装器,然后更改调用UserContext.Current的类中的代码,以注入IUserContext。在包装器中,参数less构造函数只需将private userContext设置为来自第三方lib的会话内容,我认为您应该将您使用的第三方库中的所有内容添加到IUsercontext中。您应该将IUserContact添加到IUserContext,并为IUserContact实现适配器。
public interface IThirdPartyLibraryWrapper
{
    UserContext Current { get; }
    UserContact CurrentContact { get; }
    string UserContactName { get; }
}

public class ThirdPartyLibraryWrapper 
    : IThirdPartyLibraryWrapper
{
    public UserContext Current 
    { 
        get { /* return Current from third party library */}
    }

    public UserContact CurrentContact 
    { 
        get{ /* return CurrentContact from third party library */} 
    }

    public string UserContactName 
    { 
        get{ /* return UserContactName from third party library */} 
    }
}

public class ClassUnderTest
{
    // Inject 3rd party lib
    private IThirdPartyLibraryWrapper _library;
    public virtual IThirdPartyLibraryWrapper Library
    {
        get
        {
            if (_library == null)
                _library = new ThirdPartyLibraryWrapper();
            return _library;
        }
        set
        {
            if (value != null)
                _library = value;
        }
    }

    void DoSomething(){
        UserContext Current = Library.Current; 
    }
}

[TestMethod]
public void DoSomething_WhenCalled_UsesLibraryMock()
{
    // Arrange
    UserContext fakeUserContext = new UserContext();
    Mock<IThirdPartyLibraryWrapper> libraryMock = new Mock<IThirdPartyLibraryWrapper>();
    libraryMock.Setup(l => l.Current).Returns(fakeUserContext);
    ClassUnderTest cut = new ClassUnderTest();
    cut.Library = libraryMock.Object;

    // Act
    cut.DoSomething()

    // Assert
    // ...
}