单元测试中如何Mock Service的Response对象避免空引用异常?
解决方案
问题出在ServiceStack的Service基类的Response属性未被正确初始化。单元测试场景下,服务不会自动获取请求上下文的IResponse实例,需要手动Mock并关联到服务实例。
步骤1:Mock IResponse 实例
在测试的Arrange阶段,创建IResponse的Mock对象:
var responseMock = new Mock<IResponse>();
步骤2:将Mock关联到服务
有两种可靠的方式实现关联:
方式一:直接赋值给服务的Response属性
解析出服务实例后,直接设置Response属性:
var service = BaseAppHost.Container.Resolve<EventServices>(); // 新增:设置Mock的Response service.Response = responseMock.Object;
方式二:通过RequestContext关联
如果服务依赖RequestContext获取Response,给RequestContext的Mock设置Response返回值,并确保服务的RequestContext被正确赋值:
// 在创建requestContextMock后添加 requestContextMock.Setup(x => x.Response).Returns(responseMock.Object); // 解析服务后设置RequestContext(如果容器未自动注入) var service = BaseAppHost.Container.Resolve<EventServices>(); service.RequestContext = requestContextMock.Object;
修改后的完整测试代码示例
[Test, Order(1)] public void NewEventTest_Successful() { // Arrange var request = new NewEvent { // 填充请求数据 }; var eventData = new EventData().PopulateWithNonDefaultValues(request); var eventId = new Random().NextInt64(); var eventManagerMock = new Mock<IEventManager>(); var requestContextMock = new Mock<RequestContext>(); var requestMock = new Mock<IRequest>(); // 新增:Mock IResponse var responseMock = new Mock<IResponse>(); eventManagerMock.Setup(x => x.CreateNewEvent( It.Is<EventData>(y => y.Id.Equals(eventData.Id) && // 其他断言条件 y.Metadata.Zip(eventData.Metadata, (metaY, metaR) => metaY.Key == metaR.Key && metaY.Value == metaR.Value).All(result => result) ) )).Returns(eventId) .Verifiable("IEventManager.CreateNewEvent was not invoked."); // 方式二可选:给RequestContext设置Response requestContextMock.Setup(x => x.Response).Returns(responseMock.Object); BaseAppHost.Container.Register(eventManagerMock.Object); BaseAppHost.Container.Register(requestContextMock.Object); BaseAppHost.Container.Register(requestMock.Object); // 可选:注册IResponse到容器 BaseAppHost.Container.Register(responseMock.Object); var service = BaseAppHost.Container.Resolve<EventServices>(); // 方式一:直接设置服务的Response service.Response = responseMock.Object; // 方式二:设置服务的RequestContext // service.RequestContext = requestContextMock.Object; // Act var response = service.Post(request); // Assert eventManagerMock.Verify(); // 可选:验证Response.StatusCode是否被设置为Created responseMock.VerifySet(x => x.StatusCode = (int)HttpStatusCode.Created, Times.Once); }
额外说明
如果你的服务是通过构造函数注入IResponse而非依赖基类属性,只需将responseMock.Object注册到容器即可,无需手动赋值。
内容的提问来源于stack exchange,提问作者Carlos Ramírez
相关产品推荐
相关产品推荐

