How can I mock ServiceStack IHttpRequest

2019-05-07 14:16发布

问题:

I'm trying to get a unit test working for a service that is injecting items into the IHttpRequest.Items, using a request filter:

this.RequestFilters.Add((req, res, dto) =>
{
    // simplified for readability...
    var repo = container.Resolve<IClientRepository>();
    var apiKey = req.Headers["ApiKey"];

    // lookup account code from api key
    var accountcode = repo.GetByApiKey(apiKey);
    req.Items.Add("AccountCode", accountCode);
});

My service uses that dictionary item:

public class UserService : AppServiceBase
{
    public IUserServiceGateway UserServiceGateway { get; set; }

    public object Any(UserRequest request)
    {
        var accountCode = base.Request.Items["AccountCode"].ToString();
        var user = UserServiceGateway.GetUserByUsername(request.Name);

        return new UserResponse { User = user };
    }
}

My test needs be somehow to mock the request, and insert that account code item:

[Test]
public void ValidUsernameReturnUser()
{
    // arrange 
    var gateway = new Mock<IUserServiceGateway>();
    gateway.Setup(s => s.GetUserByUsername(It.IsAny<string>()))
            .Returns(new UserAccountDTO { Forename = "John", Surname = "Doe" });

    var service = new UserService {
        UserServiceGateway = gateway.Object,
        RequestContext = new MockRequestContext(),
        //Request = has no setter
    };

    // request is this case is null
    base.Request.Items.Add("AccountCode", "DEF456");

    // act
    var response = (UserResponse)service.Any(new UserRequest { Name = "test" });

    // assert
    Assert.That(response.Result, Is.Not.Null);    
}

The service itself accepts a mocked RequestContext, but not a Request. The test therefore fails. Is there a better way to do this?

回答1:

I think this should do it.

[Test]
public void ValidUsernameReturnUser()
{
    // arrange 
    var mockRequestContext = new MockRequestContext();
    //add items to Request
    mockRequestContext.Get<IHttpRequest>().Items.Add("AccountCode", "DEF456");
    var gateway = new Mock<IUserServiceGateway>();
    gateway.Setup(s => s.GetUserByUsername(It.IsAny<string>()))
            .Returns(new UserAccountDTO { Forename = "John", Surname = "Doe" });

    var service = new UserService {
        UserServiceGateway = gateway.Object,
        RequestContext = new MockRequestContext(),
    };

    // act
    var response = (UserResponse)service.Any(new UserRequest { Name = "test" });

    // assert
    Assert.That(response.Result, Is.Not.Null);    
}