How to mock a validator for unit testing - unit-testing

I have a method that validate an Object calling an external service:
public void Validate(IValidator<MyType> validator)
{
IMapper<MyType> mapper = new MyTypeMapper();
foreach (var element in this.Elements)
{
ValidationResult result = validator.Validate(myTypeInstance, mapper, new ValidationConfiguration());
if (result.IsValid)
// do something
else
// do something else
}
}
Now in my unit test I have a collection of elements. And I want that if an element have a given id number the Validate method should return another stub with validation messages:
// arrange
var myAggregate aggregate = ElementsNonValidated.Stub();
var mockedValidator = new Mock<IValidator<MyType>>();
mockedValidator.Setup(a => a.Validate(
It.Is<Mytype>(x => x.Id == Guid.Parse("3F2504E0-4F89-11D3-9A0C-0305E82C3301")),
new Mapper(),
new ValidationConfiguration()
)).Returns<ValidationResult>(x => x = new ValidationResult());
// act
myAggregate.Valida(mockedValidator.Object);
The problem is: When unit test starts and go forth till the real method validate still return result=null. Why? What's wrong with my mock?

The problem is here:
mockedValidator.Setup(a => a.Validate(
It.Is<Mytype>(x => x.Id == Guid.Parse("3F2504E0-4F89-11D3-9A0C-0305E82C3301")),
new Mapper(),
new ValidationConfiguration()
)).Returns<ValidationResult>(x => x = new ValidationResult());
You setup Validate to expect specific Mapper and ValidationResult instances, which of course do not match the instances used in your system under test. If you don't care what instance should be used for a parameter, use It.IsAny<>:
mockedValidator.Setup(a => a.Validate(
It.Is<Mytype>(x => x.Id == Guid.Parse("3F2504E0-4F89-11D3-9A0C-0305E82C3301")),
It.IsAny<Mapper>(),
It.IsAny<ValidationConfiguration>()
)).Returns<ValidationResult>(x => x = new ValidationResult());
This will return a new ValidationResult for any and every invocation to Validate where the object's Id is equal to that particular GUID.
The reason for the TargetParameterCountException is in your Returns statement, and is answered here.

Related

Moq SetUp.Return not working for repository mock

I am trying to mock my repository's Get() method to return an object in order to fake an update on that object, but my setup is not working:
Here is my Test:
[Test]
public void TestUploadDealSummaryReportUploadedExistingUpdatesSuccessfully()
{
var dealSummary = new DealSummary {FileName = "Test"};
_mockRepository.Setup(r => r.Get(x => x.FileName == dealSummary.FileName))
.Returns(new DealSummary {FileName = "Test"}); //not working for some reason...
var reportUploader = new ReportUploader(_mockUnitOfWork.Object, _mockRepository.Object);
reportUploader.UploadDealSummaryReport(dealSummary, "", "");
_mockRepository.Verify(r => r.Update(dealSummary));
_mockUnitOfWork.Verify(uow => uow.Save());
}
Here is the method that is being tested:
public void UploadDealSummaryReport(DealSummary dealSummary, string uploadedBy, string comments)
{
dealSummary.UploadedBy = uploadedBy;
dealSummary.Comments = comments;
// method should be mocked to return a deal summary but returns null
var existingDealSummary = _repository.Get(x => x.FileName == dealSummary.FileName);
if (existingDealSummary == null)
_repository.Insert(dealSummary);
else
_repository.Update(dealSummary);
_unitOfWork.Save();
}
And here is the error that I get when I run my unit test:
Moq.MockException :
Expected invocation on the mock at least once, but was never performed: r => r.Update(.dealSummary)
No setups configured.
Performed invocations:
IRepository1.Get(x => (x.FileName == value(FRSDashboard.Lib.Concrete.ReportUploader+<>c__DisplayClass0).dealSummary.FileName))
IRepository1.Insert(FRSDashboard.Data.Entities.DealSummary)
at Moq.Mock.ThrowVerifyException(MethodCall expected, IEnumerable1 setups, IEnumerable1 actualCalls, Expression expression, Times times, Int32 callCount)
at Moq.Mock.VerifyCalls(Interceptor targetInterceptor, MethodCall expected, Expression expression, Times times)
at Moq.Mock.Verify(Mock mock, Expression1 expression, Times times, String failMessage)
at Moq.Mock1.Verify(Expression`1 expression)
at FRSDashboard.Test.FRSDashboard.Lib.ReportUploaderTest.TestUploadDealSummaryReportUploadedExistingUpdatesSuccessfully
Through debugging I have found that the x => x.FileName is returning null, but even if i compare it to null I still get a null instead of the Deal Summary I want returned. Any ideas?
I'm guessing your setup isn't matching the call you make because they're two different anonymous lambdas. You may needs something like
_mockRepository.Setup(r => r.Get(It.IsAny<**whatever your get lambda is defined as**>()).Returns(new DealSummary {FileName = "Test"});
You could verify by setting a breakpoint in the Get() method of your repository and seeing if it is hit. It shouldn't be.

Mock IDbDataAdapter Fill Method With Moq

I have an object that reads data from an Excel file using, which takes a IDbConnection, IDbDataAdapter and an IDbCommand. I use the adapters fill method to populate a table with data, and this is how I am currently mocking it:
[TestCase]
public void TestReadCellsFromSpreadsheetReadsSuccessfully()
{
var cells = new List<ReportData>
{
new ReportData { CellId = 1, ExcelCellLocation = "A1"},
new ReportData { CellId = 2, ExcelCellLocation = "A2"},
new ReportData { CellId = 3, ExcelCellLocation = "A3"},
new ReportData { CellId = 4, ExcelCellLocation = "A4"}
};
_mockAdapter.Setup(a => a.Fill(It.IsAny<DataSet>()))
.Callback((DataSet ds) =>
{
if (ds.Tables["Table"] == null)
{
ds.Tables.Add("Table");
ds.Tables["Table"].Columns.Add(new DataColumn());
}
var row = ds.Tables["Table"].NewRow();
row[0] = "Test";
ds.Tables["Table"].Rows.Add(row);
});
var excelReader = new ExcelReader(_mockConnection.Object, _mockAdapter.Object, _mockCommand.Object);
excelReader.ReadCellsFromSpreadsheet("Deal Summary", cells);
_mockCommand.VerifySet(c => c.CommandText = It.IsAny<string>(), Times.Exactly(cells.Count));
_mockAdapter.VerifySet(a => a.SelectCommand = _mockCommand.Object, Times.Exactly(cells.Count));
_mockAdapter.Verify(a => a.Fill(It.IsAny<DataSet>()), Times.Exactly(cells.Count));
}
This implementation works, but I feel like I'm doing too much to Mock the adapter... is there a better way to do this?
Do not pass those 3 objects as parameters. Instead pass IDataReader, IDataProvider or sth like that that returns data. Then You just mock this object. And you don't need reference to System.Data in project containing ExcellReader.
And two other things I don't like about your code.
Why TestCase instead of Test?
Are you sure you want to create command and fill dataset for each column separately? (but maybe I don't understand your code)
In general, I have some rules about data access:
Write a simple class that wraps all the data access logic, so that other classes don't have to deal with DataAdapters and all that crap.
When you write unit tests, don't mock out DataAdapters; instead just mock out the wrapper classes that you just created.
Make the data access wrapper logic so simple that it doesn't really need to be unit tested. If it DOES need to be tested, then write integration tests that hit a small sample database.

Using Moq to mock a repository that returns a value

How do I set up my test method on that mocks a repository which accepts an object?
This is what I have so far:
Service.cs
public int AddCountry(string countryName)
{
Country country = new Country();
country.CountryName = countryName;
return geographicsRepository.SaveCountry(country).CountryId;
}
test.cs
[Test]
public void Insert_Country()
{
//Setup
var geographicsRepository = new Mock<IGeographicRepository>();
geographicsRepository.Setup(x => x.SaveCountry(It.Is<Country>(c => c.CountryName == "Jamaica"))); //How do I return a 1 here?
GeographicService geoService = new GeographicService(geographicsRepository.Object);
int id = geoService.AddCountry("Jamaica");
Assert.AreEqual(1, id);
}
SaveCountry(Country country); returns an int.
I need to do 2 things:
First test, I need to tell the setup to return an int of 1.
I need to create a second test Insert_Duplicate_Country_Throws_Exception(). In my Setup, how do I tell the repository to throw an error when I do:
int id = geoService.AddCountry("Jamaica");
int id = geoService.AddCountry("Jamaica");
Framework:
NUnit.
Moq.
ASP.NET MVC - repository pattern.
Your first test should look something like this:
[Test]
public void Insert_Country()
{
Mock<IGeographicRepository> geographicsRepository = new Mock<IGeographicRepository>();
GeographicService geoService = new GeographicService(geographicsRepository.Object);
// Setup Mock
geographicsRepository
.Setup(x => x.SaveCountry(It.IsAny<Country>()))
.Returns(1);
var id = geoService.AddCountry("Jamaica");
Assert.IsInstanceOf<Int32>(id);
Assert.AreEqual(1, id);
geographicsRepository.VerifyAll();
}
The second test should look like this:
[Test]
public void Insert_Duplicate_Country_Throws_Exception()
{
Mock<IGeographicRepository> geographicsRepository = new Mock<IGeographicRepository>();
GeographicService geoService = new GeographicService(geographicsRepository.Object);
// Setup Mock
geographicsRepository
.Setup(x => x.SaveCountry(It.IsAny<Country>()))
.Throws(new MyException());
try
{
var id = geoService.AddCountry("Jamaica");
Assert.Fail("Exception not thrown");
}
catch (MyException)
{
geographicsRepository.VerifyAll();
}
}
I think maybe you are slightly misunderstanding the purpose of testing with mocks in the two scenarios you have supplied.
In the first scenario, you wish to test that 1 is returned when you pass in "Jamaica". This is not a mock test case but a test case for real behaviour as you wish to test a specific input against an expected output i.e. "Jamaica" -> 1. In this situation mocking is more useful to ensure that internally your service calls SaveCountry on the repository with the expected country, and that it returns the value from the call.
Setting up your "SaveCountry" case and then calling "VerifyAll" on your mock is the key. This will assert that "SaveCountry" was indeed called with country "Jamaica", and that the expected value is returned. In this way you have confidence that your service is wired up to your repository as expected.
[Test]
public void adding_country_saves_country()
{
const int ExpectedCountryId = 666;
var mockRepository = new Mock<IGeographicRepository>();
mockRepository.
Setup(x => x.SaveCountry(It.Is<Country>(c => c.CountryName == "Jamaica"))).
Returns(ExpectedCountryId);
GeographicService service= new GeographicService(mockRepository.Object);
int id = service.AddCountry(new Country("Jamaica"));
mockRepo.VerifyAll();
Assert.AreEqual(ExpectedCountryId, id, "Expected country id.");
}
In the second scenario you wish to test that an exception is raised when you attempt to add a duplicate country. There's not much point in doing this with a mock as all you will test is that your mock has behaviour when adding duplicates, not your real implementation.

Returning a complex data type from arguments with Rhino Mocks

I'm trying to set up a stub with Rhino Mocks which returns a value based on what the parameter of the argument that is passed in.
Example:
//Arrange
var car = new Car();
var provider= MockRepository.GenerateStub<IDataProvider>();
provider.Stub(
x => x.GetWheelsWithSize(Arg<int>.Is.Anything))
.Return(new List<IWheel> {
new Wheel { Size = ?, Make = Make.Michelin },
new Wheel { Size = ?, Make = Make.Firestone }
});
car.Provider = provider;
//Act
car.ReplaceTires();
//Assert that the right tire size was used when replacing the tires
The problem is that I want Size to be whatever was passed into the method, because I'm actually asserting later that the wheels are the right size. This is not to prove that the data provider works obviously since I stubbed it, but rather to prove that the correct size was passed in.
How can I do this?
"This is not to prove that the data provider works ... but rather to prove that
the correct size was passed in."
Not sure if it works that well for this particular case, but generally I've found it easiest to test these sorts of things indirectly via the stub.
Rather than checking the output of the stubbed call, explicitly specify the arguments to your stub and then verify that the return value was used as expected (regardless of the actual data returned). If it was, then you know that your stub was called correctly.
//Arrange
var wheels = new List<IWheel>();
const int wheelSize = 17;
var car = new Car();
car.WheelSize = wheelSize;
var provider= MockRepository.GenerateStub<IDataProvider>();
provider
.Stub(x => x.GetWheelsWithSize(wheelSize))
.Return(wheels);
car.Provider = provider;
//Act
car.ReplaceTires();
//Assert that the right-sized wheels from the provider were
//used when replacing the tires
Assert.That(car.Wheels, Is.SameAs(wheels));
If this approach doesn't work for you in this case then you can use WhenCalled to inspect the call arguments and/or modify the return value.
provider
.Stub(x => x.GetWheelsWithSize(Arg<int>.Is.Anything))
.WhenCalled(x => x.ReturnValue = CreateWheelsOfSize((int) x.Arguments[0]));
In this case CreateWheelsOfSize(int) will just create your list of wheels.
Hope this helps.
You can use the Do() functionality in order to achieve dynamic return value. For example:
[Test]
public void DynamicallyFakeReturnValue()
{
var calculatorStub = MockRepository.GenerateStub<ICalculator>();
calculatorStub.Stub(address => address.AddOne(Arg<int>.Is.Anything))
.Do((Func<int, int>) (x => x - 1));
Assert.That(calculatorStub.AddOne(1), Is.EqualTo(0));
}
In your case it will probably be:
provider.Stub(
x => x.GetWheelsWithSize(Arg<int>.Is.Anything))
.Do((Func<int, List<IWheel>>) (size => new List<IWheel> {
new Wheel { Size = size, Make = Make.Michelin },
new Wheel { Size = size, Make = Make.Firestone }
}));

Moq - How to unit test changes on a reference in a method

Another day , another question. My service layer has the following method
public MatchViewData CreateMatch(string user)
{
var matchViewData = !HasReachedMaxNumberOfMatchesLimit(user) ?
CreateMatchAndAddToRepository(user) :
MatchViewData.NewInstance(new Match(user));
matchViewData.LimitReached = HasReachedMaxNumberOfMatchesLimit(user);
return matchViewData;
}
The method calls the this helper method to create a new match object:
private MatchViewData CreateMatchAndAddToRepository(string user)
{
var match = new Match(user);
MatchRepository.Add(match);
return MatchViewData.NewInstance(match);
}
The repository stores the given match object and sets the id to some value > 0.
public void Add(Match match)
{
Check.Require(match != null);
var numberOfMatchesBefore = Matches.Count;
SetIdPerReflection(match, NextVal());
Matches.Add(match);
Check.Ensure(numberOfMatchesBefore == Matches.Count - 1);
}
The matchviewdata object copies some properties of the the match object (including the id).
My unit test should verify that the resulting viewdata object in the service has an id > 0. To archieve this, i have to mock the repository and the behaviour of the add method. But the service method creates a new match object every time its been called and the add method on the repository updates the referenced match object (there is no need for a return value). I have no idea to solve this with moq.
This is my unit test so far:
[Test]
public void ServiceCreateMatchReturnedMatchViewDataHasNonZeroId()
{
var match = TestUtils.FakePersistentMatch(User, 1);
var repositoryMock = new Mock<IMatchRepository>();
repositoryMock.Setup(
r => r.Add(It.IsAny<Match>())).Callback(() => match.Id = 1);
var serviceFacade = new DefaultServiceFacade(repositoryMock.Object);
var returnedMatch = serviceFacade.CreateMatch(User);
Assert.That(returnedMatch.Id, Is.GreaterThan(0));
}
I tried some other variations - nothing works.
It looks to me your problem is in this line;
repositoryMock.Setup(
r => r.Add(It.IsAny<Match>())).Callback(() => match.Id = 1);
What you're actually doing here is setting the id of the first match object you have declared in your test, NOT the new match created in your service.
Because the Match object you will be supplying to the Repository is created internally, I can't think of an easy way to reference it in your Test method to setup a callback for it. To me, this is a sign you may be trying to test too much in one unit test.
I think you should simply test that the Add method is called and write a separate test to ensure that it works as exepected.
I propose something like this;
[Test]
public void ServiceAddsNewMatchToRepository()
{
var repositoryMock = new Mock<IMatchRepository>();
bool addCalled = false;
repositoryMock
.Expect(r => r.Add(It.Is<Match>(x => x.Id == 0))
.Callback(() => addCalled = true);
var serviceFacade = new DefaultServiceFacade(repositoryMock.Object);
serviceFacade.CreateMatch(User);
Assert.True(addCalled);
}
....
[Test]
public void AddingANewMatchGeneratesANewId()
{
var match = new Match(user);
var matchRepository = new MatchRepository();
var returnedMatch = matchRepository.Add(match);
Assert.That(returnedMatch.Id, Is.GreaterThan(0));
}