假设我有一个这样的课程:
public class Context {
public void initialize() { ... }
}
和另一个使用它的课程:
public class Service {
public Context getContext() { return context; }
internal Service(Context ctx) {
context = ctx;
context.initialize();
}
private Context context;
}
最后,假设我想为Service
编写单元测试,以验证在构建类时调用Context.initalize
。由于它是一个单元测试,我想模拟Context
而不是使用真正的类。使用Moq需要创建一个接口IContext
并重写代码如下:
public interface IContext {
void initialize();
}
public class Context : IContext {
public void initialize() { ... }
}
public class Service {
public IContext getContext() { return context; }
internal Service(IContext ctx) {
context = ctx;
context.initialize();
}
private IContext context;
}
[TestFixture()]
public class ServiceTest {
[Test()]
public shouldInitializeContextWhenConstructed() {
Mock<IContext> mockContext = new Mock<IContext>();
Service service = new Service(mockContext);
mockContext.Verify(c => c.initialize(), Times.Once());
}
}
但是,由于IContext
纯粹是与测试相关的工件,因此我希望避免将其暴露给Service
类的用户(通过Service.getContext
函数)。这里的解决方案是什么?
答案 0 :(得分:1)
我的解决方案是将IContext
标记为internal
并使用as
运算符将context
投射到Context
。这是安全的,因为当用户使用时,实际context
始终为Context
:
internal interface IContext {
void initialize();
}
public class Context : IContext {
public void initialize() { }
}
public class ServiceFactory {
public static Service createService() { return new Service(new Context()); }
}
public class Service {
public Context getContext() { return context as Context; }
internal Service(IContext ctx) {
context = ctx;
context.initialize();
}
private IContext context;
}
[TestFixture()]
public class ServiceTest {
[Test()]
public void shouldInitializeContextWhenConstructed() {
Mock<IContext> mockContext = new Mock<IContext>();
new Service(mockContext.Object);
mockContext.Verify(c => c.initialize(), Times.Once());
}
}