没有 setter 的模拟对象
Mock objects with no setter
我正在使用第三方库 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 的子类并覆盖 Current 属性:
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(第 3 方库)会话内容用于生产代码,以及一个可以接收自定义 UserContextFake 的构造函数。在 IoC 中,我将 IUserContext 映射到 UserContext
问题:如果 CurrentContact 不在界面中而是 UserContext (UserContext.CurrentContact)
的 属性,我该如何模拟它
你不能为整个 3dr 派对库创建一个界面吗?然后实现这个接口并使用这个 class 作为第 3 方库的包装器。方法。在 class under test 然后添加例如属性 可用于注入接口的模拟。示例(未经测试)。 HTH
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
// ...
}
我正在使用第三方库 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 的子类并覆盖 Current 属性:
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(第 3 方库)会话内容用于生产代码,以及一个可以接收自定义 UserContextFake 的构造函数。在 IoC 中,我将 IUserContext 映射到 UserContext
问题:如果 CurrentContact 不在界面中而是 UserContext (UserContext.CurrentContact)
的 属性,我该如何模拟它你不能为整个 3dr 派对库创建一个界面吗?然后实现这个接口并使用这个 class 作为第 3 方库的包装器。方法。在 class under test 然后添加例如属性 可用于注入接口的模拟。示例(未经测试)。 HTH
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
// ...
}