Reputation: 4809
I am trying to write simple unit test for ServiceStack service, I am going through tests they've online and few threads here. This is the main thread that has most details I am trying to accomplish - Unit Test HTTPRequest Headers with ServiceStack.
However, I am facing problems injecting IDbConnection object into the service. In the webmethod, a dictionary object is populated by using OrmLite's GetDictionary method. But I am unable to mock it since GetDictionary is extension method.
private Mock<IDbConnection> _dbConnectionMock;
private Dictionary<string, string> _nameValuePairs;
[SetUp]
public void SetUp()
{
_dbConnectionMock = new Mock<IDbConnection>();
_nameValuePairs = new Dictionary<string, string>()
{
{"name","test"},
{"Updatedby", "5/23/12 7:00:15 AM"},
{"Address", "212 Adam St."}
};
}
In test method
var service = new CustomerLookupService(_dbConnectionMock.Object);
var response = (HttpResult)service.Any(new CustomerLookup { name = "test" });
//assert statements
If GetDictionary method cannot be mocked, I am even willing to call web method that hits DB, for this do I need to create AppHost.
Upvotes: 4
Views: 1227
Reputation: 4816
I think there are a couple of options to look into.
Mocking/stubbing/unit-testing extension methods here, here or various other spots. I don't think there is a preferred way to do this but there are some options and frameworks/libraries to help.
Running an in memory database such as Sqlite for your unit tests. See here.
You could abstract the IDConnection into a CustomerLookUpRepository and inject your CustomerLookUpRepository into your service. Then you can just mock your 'Repository'.
I've given this 'arrangement' a try. So far it seems to work for most basic cases. The data access pattern is taking from the Redis Web Service example. YMMV, though.
Test (using RhinoMocks)
public void SomeTest()
{
var _nameValuePairs = new Dictionary<string, string>()
{
{"name","test"},
{"Updatedby", "5/23/12 7:00:15 AM"},
{"Address", "212 Adam St."}
};
var mockSqlRepository = MockRepository.GenerateMock<ISqlRepository>();
mockSqlRepository.Stub(
x => x.Exec(Arg<Func<IDbConnection, Dictionary<string, string>>>.Is.NotNull)).Return(_nameValuePairs);
var service = new CustomerLookupService { SqlRepository = mockSqlRepository }
//MORE TEST CODE...
}
Service class - using ISqlRepository to abstract/hide IDbConnection. ISqlRepository has a function that takes a function as the parameter. The function signature (of the parameter) takes IDbConnection as a parameter so I don't have to write several methods to access the database.
public class CustomerLookupService
{
public ISqlRepository SqlRepository { get; set; }
public void Any(CustomerLookup request)
{
var results =
SqlExec<Dictionary<string, string>>((con) => con.GetDictionary<type, type>("Select id, name from table"));
//MORE SERVICE CODE
}
public T SqlExec<T>(Func<IDbConnection, T> fn)
{
return SqlRepository.Exec(fn);
}
}
ISqlRepository
public interface ISqlRepository
{
T Exec<T>(Func<IDbConnection, T> fn);
}
SqlRepository
public class SqlRepository : ISqlRepository
{
public IDbConnectionFactory DbFactory { get; set; }
public T Exec<T>(Func<IDbConnection, T> fn)
{
using (var con = DbFactory.OpenDbConnection())
{
return fn(con);
}
}
}
Upvotes: 3