Reputation: 412
I'm trying to mock (using Rhino.Mocks) a DataService which returns an IDataReader. I Can mock the IDataReader (StackOverFlow Q 1792984) but if I then Stub out A Data Service which returns this DataReader and inject it into the method I am trying to test it the stub returns only a null Data Reader.
IDataService
public interface IDataService
{
SqlDataReader ExecuteReader(string cmdText, CommandType commandType);
<rest of definition ommited
}
Unit test
[TestMethod]
public void GetCustomer_Pass()
{
//Arrange
var customer = new Customer()
{
Id = 1, FirstName = "Patrick",
LastName = "Hastings", ProfilePictureURL = ""
};
var mockDataService = MockRepository.GenerateStub<IDataService>();
var reader = MockRepository.GenerateStub<IDataReader>();
reader.Stub(x => x.Read()).Repeat.Once().Return(true);
reader.Stub(x => x.Read()).Return(false);
reader.Stub(x => x["Id"]).Return(customer.Id);
reader.Stub(x => x["FirstName"]).Return(customer.FirstName);
reader.Stub(x => x["LastName"]).Return(customer.LastName);
reader.Stub(x => x["ProfilePictureURL"]).Return(customer.ProfilePictureURL);
mockDataService.Stub( s =>
s.ExecuteReader(string.Format("select FirstName, LastName,ProfilePictureURL from customer where Id = {0}", customer.Id),
CommandType.Text))
.Return(reader as SqlDataReader);
var custRepository = new CustomerRepository(mockDataService);
//Act
var customer2 = custRepository.GetCustomer(1);
//Assert
Assert.AreEqual(customer.FirstName, customer2.FirstName,"FirstName Mismatch");
Assert.AreEqual(customer.LastName, customer2.LastName, "LastName Mismatch");
}
Method UnderTest
public CustomerRepository(IDataService dataService) //Constructor
{
if (dataService == null) throw new ArgumentNullException("dataService", "dataService cannot be null.");
this.dataService = dataService;
}
public Customer GetCustomer(int id)
{
var sql =string.Format("select FirstName, LastName, ProfilePictureURL from customer where Id = {0}",id);
var dr = dataService.ExecuteReader(sql, CommandType.Text);
Customer customer ;
using (dr)
{
if (!dr.Read()){return null;}
customer = new Customer
{
FirstName = dr["FirstName"].ToString(),
LastName = dr["LastName"].ToString(),
ProfilePictureURL = dr["ProfilePictureURL"].ToString()
};
}
return customer;
}
This issue that I get is that when "dataService.ExecuteReader(sql, CommandType.Text);" should return the mocked IDataReader but instead returns Null - any pointers as to what I am doing wrong would be gratefully appreciated.
Upvotes: 1
Views: 2657
Reputation: 62544
First point:
I believe because of different arguments passed into the ExecuteReader() method:
Set in expectation:
"select FirstName, LastName,ProfilePictureURL...
Passed whilst actual call: (extra space between comma and ProfilePictureURL)
"select FirstName, LastName, ProfilePictureURL...
Sometimes IgnoreArguments()
is pretty useful when argument itself does not matter
Second Point:
.Return(reader as SqlDataReader);
This is invalid cast because reader is a mock object created by RhinoMock.
I believe you do not need a SqlDataReader type so just return reader itself
.Return(reader)
PS: Also I would suggest store values which are repeating as constants, you can store customerId = 1
as constant as well to avoid such possible issues.
Upvotes: 1