0

假设我有这样的课程:

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而不是使用真正的类。使用需要创建接口IContext并重写代码的 Moq 如下:

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函数)。这里的正确解决方案是什么?

4

1 回答 1

1

我的解决方案是标记IContextinternal并使用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());
    }
}
于 2013-09-12T14:23:25.710 回答