chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
0 votes
I have a generic repository that connects to the Entity Framework. I'm trying to write a test to validate "GetUser(int userId)", which then calls "First(Func<T, bool> exp)" (The First method has code for the case that no record is found), and First calls "GetAll(Func<T, bool> exp)" which returns an IQueryable.

(A simplified call chain looks like this):
GetUser(1) -> First(userId == 1) -> GetAll()

Now we could just make the call directly from the UserRepository.GetUser(int userId) into GetAll(Func<T, bool> exp), but we are using First in order to keep the code as DRY as possible.

When creating a Unit Test using Isolator, I found that we GetAll() to return a stubbed list, then First(...) to CallOriginal (which doesn't feel right because now we're testing that method as well as GetUser, but maybe it is correct), and then finally GetUser, telling it to do a .CallOriginal.

The other piece that doesn't feel right is where we are actually providing the "UserId" and "u => u.UserId == UserId" as part of the .WhenCalled statement. Is there something that I'm missing that tells the Mock or Stub to take any argument in as they are sent and work with that?

(I can provide a sample of the code if it would help answering the question)


public void GetUser_WithAValidUserId_ReturnsaValidUser()
const int UserId = 1;

var userList = RepositoryTestSetupWithJustMock.GetStubbedListOfUsers();

UserRepository fakeRepository = Isolate.Fake.Instance<UserRepository>();

Isolate.WhenCalled(() => fakeRepository.GetAll()).WillReturn(userList);
Isolate.WhenCalled(() => fakeRepository.First(u => u.UserId == UserId)).CallOriginal();
Isolate.WhenCalled(() => fakeRepository.GetUser(UserId)).CallOriginal();

User actual = fakeRepository.GetUser(UserId);

Assert.AreEqual(UserId, actual.UserId);
asked by swilkos (600 points)

1 Answer

0 votes

When using WhenCalled on a method that takes parameters, unless you don't specify .WithExactArguments, or .WithArguments, then isolator doesn't look at the value of the arguments at all. So you could change your code to:

Isolate.WhenCalled(() => fakeRepository.First(null)).CallOriginal();
Isolate.WhenCalled(() => fakeRepository.GetUser(0)).CallOriginal();

Another option is to instantiate a real object of UserRepository and just change the behavior of GetAll method. However, if the constructor of UserRepository goes for example to the DB, then this might not be feasible. Your code would then look like this:

UserRepository repository = new UserRepository(/* here you might need to fake some arguments */);
var userList = RepositoryTestSetupWithJustMock.GetStubbedListOfUsers();
Isolate.WhenCalled(() => repository.GetAll()).WillReturn(userList);

User actual = repository.GetUser(UserId);

Assert.AreEqual(UserId, actual.UserId);
answered by yoel (1.9k points)