Verifying a virtual method (MOQ) - c#

So I am new to TDD and here is my problem:
I have a class with several methods. Something like this:
public class CompanyService : ICompanyService
{
public ICompanyRepository companyRepository;
public CompanyService() : this(new CompanyRepository())
{
}
public CompanyService(ICompanyRepository repository)
{
companyRepository = repository;
}
public virtual bool InsertCompany(Company company)
{
return companyRepository.InsertCompany(company);
}
public bool InsertCompany(Company company, int total)
{
if (AddTotals(total))
{
return this.InsertCompany(company);
}
return false;
}
/// <summary>
/// Wrapper for the static method at static service
/// </summary>
/// <param name="total"></param>
/// <returns></returns>
public virtual bool AddTotals(int total)
{
return StaticService.AddTotals(total);
}
}
Most of my tests run fine for this class. So here is my unit test:
[TestMethod]
public void Test_Unit_AddTotals()
{
var service = new CompanyService();
Assert.IsFalse(service.AddTotals(1));
}
[TestMethod]
public void Test_Unit_InsertCompany_IsExecuted()
{
Guid id = GenerateCustomerID();
var company = new Company { CustomerID = id, CompanyName = "CFN-" + id };
var mock = new Mock<CompanyService>();
mock.Setup(t => t.AddTotals(It.IsAny<int>())).Returns(true);
mock.Object.InsertCompany(company, 1);
mock.Verify(t => t.InsertCompany(It.IsAny<Company>()),Times.Once);
}
[TestMethod]
public void Test_Unit_InsertCompany_IsSuccess()
{
Guid id = GenerateCustomerID();
var company = new Company { CustomerID = id, CompanyName = "CFN-" + id };
var mock = new Mock<CompanyService>();
mock.Setup(t => t.AddTotals(It.IsAny<int>())).Returns(true);
mock.Setup(t => t.InsertCompany(It.IsAny<Company>(), It.IsAny<int>())).Returns(true);
Assert.IsTrue(mock.Object.InsertCompany(company, 1));
}
[TestMethod]
public void Test_Unit_StaticService()
{
var rep = new Mock<ICompanyRepository>();
rep.Setup(t => t.InsertCompany(It.IsAny<Company>())).Returns(true);
var serviceMock = new Mock<ICompanyService>();
serviceMock.Setup(t => t.AddTotals(It.IsAny<int>())).Returns(true);
Assert.IsTrue(serviceMock.Object.AddTotals(0));
}
private Guid GenerateCustomerID()
{
return Guid.NewGuid();
}
So when I make my 2 parameter InsertCompany method virtual my IsExecuted method fails at Verify, if I make it non-virtual, then I can't mock it for IsSuccess method and it fails..
Could you please tell me what I am missing with your TDD expertise?

As has been suggested in the comments, you're almost certainly not testing the right thing. Look at this test:
[TestMethod]
public void Test_Unit_InsertCompany_IsSuccess()
{
Guid id = GenerateCustomerID();
var company = new Company { CustomerID = id, CompanyName = "CFN-" + id };
var mock = new Mock<CompanyService>();
mock.Setup(t => t.AddTotals(It.IsAny<int>())).Returns(true);
mock.Setup(t => t.InsertCompany(It.IsAny<Company>(), It.IsAny<int>())).Returns(true);
Assert.IsTrue(mock.Object.InsertCompany(company, 1));
}
If your class is marked with the right virtual state for the Setup to execute, then you're not actually testing any of your class at all. You're setting up the Mock to return true when a method is called, then asserting that when you call the method the mock returns true... You're just testing that you've set your Mocks up correctly.
When you mark the method as virtual, your mocking used in the IsExecuted method is failing, because you're calling virtual methods from within the class under test. If you don't tell it to, Moq will assume that if you're doing a partial mock, you only want your mocked virtuals to be called, not the existing implementation. You can override this by telling Moq to call your existing implementation by setting the CallBase flag.
Your test would then become this:
[Test]
public void Test_Unit_InsertCompany_IsExecuted() {
Guid id = GenerateCustomerID();
var company = new Company { CustomerID = id, CompanyName = "CFN-" + id };
var mock = new Mock<CompanyService>();
mock.CallBase = true;
mock.Setup(t => t.AddTotals(It.IsAny<int>())).Returns(true);
mock.Setup(t => t.InsertCompany(It.IsAny<Company>()));
mock.Object.InsertCompany(company, 1);
mock.Verify(t => t.InsertCompany(It.IsAny<Company>()), Times.Once);
}
Two things to note are
In the above test, CallBase=true is used to execute existing code.
As a result of 1, it's necessary to perform a Setup for the call you want to verify, otherwise the call will actually execute the underlying code and call out to the repository.
Testing that one method calls another method in the same class isn't really a great idea. It can get very messy and makes it difficult to know that what you're expecting to happen is actually what's happening as well as tightly coupling your implementation to your test code.
You've already setup your Company class to allow the injection of a repository. Testing that the appropriate repository interactions take place would result in less coupling to the implementation of your Company class and would probably result in more straightforward mocking.
Using that approach, your IsExecuted test might become:
[Test]
public void Test_Unit_InsertCompany_SavesToRepository() {
Guid id = GenerateCustomerID();
var repoMock = new Mock<ICompanyRepository>();
var company = new Company { CustomerID = id, CompanyName = "CFN-" + id };
var mock = new Mock<CompanyService>(repoMock.Object);
mock.CallBase = true;
mock.Setup(t => t.AddTotals(It.IsAny<int>())).Returns(true);
mock.Object.InsertCompany(company, 1);
repoMock.Verify(t => t.InsertCompany(It.IsAny<Company>()), Times.Once);
}
Ideally, you'd be able to Mock the interaction with StaticService.AddTotals, that way you would be able to instantiate an actual CompanyService, rather than a mock object in your tests, however that seems out of scope for your current problem...

Related

Rhino Mocks exception "Expected #1, Actual #0" in apparently working code

I have a piece of code from an old book on MVVM which works, but a test using Rhino Mocks fails with this message:
Test method TestProject.UnitTest1.UpdateCustomer_Always_CallsUpdateWithCustomer threw exception:
Rhino.Mocks.Exceptions.ExpectationViolationException: DataProvider.DoSomething(ConsoleApp.Customer); Expected #1, Actual #0
I'm providing an example which I think is equivalent:
namespace ConsoleApp {
class Program { static void Main () { } }
public class Customer { public string ID { get; set; } }
public class DataProvider {
public virtual Customer GetCustomer (string id) => new Customer ();
public virtual void DoSomething (Customer customer) { }
}
public class ViewModel {
DataProvider _dataProvider;
Customer _customer;
public ViewModel (DataProvider dataProvider, string id) {
_dataProvider = dataProvider;
_customer = new Customer { ID = id };
}
public void DoSomething () => _dataProvider.DoSomething (_customer);
}
}
and the test that fails
namespace TestProject {
[TestClass]
public class UnitTest1 {
[TestMethod]
public void UpdateCustomer_Always_CallsUpdateWithCustomer () {
DataProvider dataProviderMock = MockRepository.GenerateMock<DataProvider> ();
Customer expectedCustomer = new Customer ();
dataProviderMock.Stub (u => u.GetCustomer (Arg<string>.Is.Anything)).Return (expectedCustomer);
ViewModel target = new ViewModel (dataProviderMock, string.Empty);
target.DoSomething ();
dataProviderMock.AssertWasCalled (d => d.DoSomething (expectedCustomer));
}
}
}
I read several posts on this result, e.g. 1 and 2, but this doesn't help me. I read this answer which seems interesting:
I usually get this error when a stubbed method is called with an object argument
that I build in the test and in the tested code the object is built before calling that method.
While this could be a reason for the Rhino Mocks to fail, it seems to be a bug.
My question is: Is there something wrong in my test and there is a bug in Rhino Mocks, or is there a problem with my code?
The test stubs DataProvider.GetCustomer to return an expected customer instance to be used in the assertion, but the example view model does not invoke DataProvider.GetCustomer.
It is using the one initialized in the constructor.
//...
public ViewModel (DataProvider dataProvider, string id) {
_dataProvider = dataProvider;
_customer = new Customer { ID = id };
}
//...
Thus the exception thrown by the test is accurate given the shown example.
That is because the actual instance used by the view model will not be the one used in the assertion when the test is exercised.
//...
dataProviderMock.AssertWasCalled (d => d.DoSomething (expectedCustomer));
In order for the test to behave as expected based on its arrangement the view model would actually have be refactored to decouple from initializing the Customer
For example
public class ViewModel {
DataProvider _dataProvider;
string id;
public ViewModel (DataProvider dataProvider, string id) {
_dataProvider = dataProvider;
this.id = id;
}
public void DoSomething () {
Customer customer = _dataProvider.GetCustomer(id);
_dataProvider.DoSomething (_customer);
}
}
The test should also be more explicit about what it is trying to test
[TestClass]
public class UnitTest1 {
[TestMethod]
public void UpdateCustomer_Always_CallsUpdateWithCustomer () {
//Arrange
DataProvider dataProviderMock = MockRepository.GenerateMock<DataProvider> ();
string id = "FakeId";
Customer expectedCustomer = new Customer { ID = id };
dataProviderMock.Stub (u => u.GetCustomer (id))
.Return (expectedCustomer);
ViewModel target = new ViewModel (dataProviderMock, id);
//Act
target.DoSomething ();
//Assert
dataProviderMock.AssertWasCalled (d => d.DoSomething (expectedCustomer));
}
}
Alternatively, if the view model is as intended then the test needs to assert its expectations differently
[TestClass]
public class UnitTest1 {
[TestMethod]
public void UpdateCustomer_Always_CallsUpdateWithCustomer () {
//Arrange
DataProvider dataProviderMock = MockRepository.GenerateMock<DataProvider> ();
string id = "FakeId";
ViewModel target = new ViewModel (dataProviderMock, id);
//Act
target.DoSomething ();
//Assert
dataProviderMock
.AssertWasCalled (d => d.DoSomething (Arg<Customer>.Matches(c => c.ID == id));
}
}
Note the delegate used in the assertion to verify the characteristics of the expected argument instead of the specific instance passed when it was invoked.

Override Autofixture customization setup

I've a class with several services injected in its constructor. I'm using Autofixture with xUnit.net and NSubstitute, and created an attribute to setup the global customization.
public class AutoDbDataAttribute : AutoDataAttribute
{
public AutoDbDataAttribute() : base(() => new Fixture().Customize(new AutoNSubstituteCustomization()))
{
}
public AutoDbDataAttribute(Type customizationType) : base(() =>
{
var customization = Activator.CreateInstance(customizationType) as ICustomization;
var fixture = new Fixture();
fixture.Customize(new AutoNSubstituteCustomization());
fixture.Customize(customization);
return fixture;
})
{
}
}
I also have a custom customization class that setups the common customization for the test methods in the same class.
public class RevenueProviderCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Register<IRevenueContextService>(() =>
{
var contextService = Substitute.For<IRevenueContextService>();
contextService.GetContext().Returns(fixture.Create<RevenueContext>());
return contextService;
});
fixture.Register<ICompanyService>(() =>
{
var companyService = Substitute.For<ICompanyService>();
companyService.Get(Arg.Any<Guid>()).Returns(fixture.Create<Company>());
return companyService;
});
}
}
Now, some of my tests depend on modifying specific properties in the objects returned by the services. So in some cases, I want to modify the RevenueContext and in some cases, I want to modify the Company data.
What I did was creating another object inside the test itself and modify the Returns of the service with the new object, like this:
[Theory]
[AutoDbData(typeof(RevenueProviderCustomization))]
public void ShouldReturnCompanyRevenue(RevenueProvider sut, Company company, [Frozen]IRevenueContextService contextService)
{
var fixture = new Fixture();
RevenueContext context = fixture.Build<RevenueContext>().With(c => c.DepartmentId, null).Create();
contextService.GetContext().Returns(context);
sut.GetRevenue().Should().Be(company.Revenue);
}
But this doesn't work. The RevenueContext from the RevenueProviderCustomization is still used.
Does anyone know how I can override the return from the service? I don't want to setup the fixture one by one in my test, so I was hoping to be able to create a 'general setup' and modify as needed according to the test case.
UPDATE 1
Trying the answer from Mark, I changed the test to
[Theory]
[AutoDbData(typeof(RevenueProviderCustomization))]
public void ShouldReturnCompanyRevenue([Frozen]IRevenueContextService contextService, [Frozen]Company company, RevenueProvider sut, RevenueContext context)
{
context.DepartmentId = null;
contextService.GetContext().Returns(context);
sut.GetRevenue().Should().Be(company.Revenue);
}
The problem is because the RevenueContext is called in the RevenueProvider constructor. So my modification to the DepartmentId happens after the call was made.
public RevenueProvider(IRevenueContextService contextService, ICompanyService companyService)
{
_contextService = contextService;
_companyService = companyService;
_company = GetCompany();
}
public double GetRevenue()
{
if (_hasDepartmentContext)
return _company.Departments.Single(d => d.Id == _departmentId).Revenue;
else
return _company.Revenue;
}
private Company GetCompany()
{
RevenueContext context = _contextService.GetContext();
if (context.DepartmentId.HasValue)
{
_hasDepartmentContext = true;
_departmentId = context.DepartmentId.Value;
}
return _companyService.Get(context.CompanyId);
}
Assuming that RevenueProvider essentially looks like this:
public class RevenueProvider
{
private readonly ICompanyService companySvc;
public RevenueProvider(ICompanyService companySvc)
{
this.companySvc = companySvc;
}
public object GetRevenue()
{
var company = this.companySvc.Get(Guid.Empty);
return company.Revenue;
}
}
Then the following test passes:
[Theory]
[AutoDbData(typeof(RevenueProviderCustomization))]
public void ShouldReturnCompanyRevenue(
[Frozen]ICompanyService companySvc,
RevenueProvider sut,
Company company)
{
companySvc.Get(Arg.Any<Guid>()).Returns(company);
var actual = sut.GetRevenue();
Assert.Equal(company.Revenue, actual);
}
This scenario is exactly what the [Frozen] attribute is designed to handle. The various attributes that AutoFixture defines are applied in the order of the arguments. This is by design, because it enables you to pull out a few values from the argument list before you freeze a type.
In the OP, [Frozen] is only applied after sut, which is the reason the configuration of the mock doesn't apply within the SUT.

Write Moq Unit Test for internal method in the same class using Autofac

I am trying mock internal method in the same class.But my mocking fails.
Here is my code.
Interface
public interface IStudentService
{
int GetRank(int studentId);
IList<Subject> GetSubjects(int studentId);
}
Implementation
public class StudentService : IStudentService
{
private readonly IStudentRepository _studentRepository;
private readonly ISubjectRepository _subjectRepository;
public StudentService(IStudentRepository studentRepository, ISubjectRepository subjectRepository)
{
_studentRepository = studentRepository;
_subjectRepository = subjectRepository;
}
public int GetRank(int studentId)
{
IList<Subject> subjects = GetSubjects(studentId);
int rank = 0;
//
//Calculate Rank
//
return rank;
}
public virtual IList<Subject> GetSubjects(int studentId)
{
return _subjectRepository.GetAll(studentId);
}
}
Unit Test
[TestFixture]
public class StudentServiceTest
{
[SetUp]
public void Setup()
{
}
[TearDown]
public void TearDown()
{
}
[Test]
public void GetRankTest()
{
using (var mock = AutoMock.GetStrict())
{
var mockStudentService = new Mock<IStudentService>();
mockStudentService.Setup(x => x.GetSubjects(1)).Returns(new ServiceResponse<SystemUser>(new List<Subject>{ new AccounProfile(), new AccounProfile()}));
mock.Provide(mockStudentService.Object);
var component = mock.Create<StudentService>();
int rank = component.GetRank(1);
mockStudentService.VerifyAll();
Assert.AreEqual(1, rank, "GetRank method fails");
}
}
}
When I debug the code it is not mocking the GetSubjects method. It actually go inside to that method. I am using Nunit, Moq and Autofac to write unit test.
Thanks In Advance!
There are two solutions.
1. Partial mocking
In this approach you create mock of component you're testing (StudentService) and tell Moq to mock some of its methods (GetSubjects -- to-be-mocked methods must be virtual), while delegating others (GetRank) to base implementation:
Setting mock.CallBase = true instructs Moq to delegate any call not matched by explicit Setup call to its base implementation.
// mockStudentService is not needed, we use partial mock
var service = mock.Create<StudentService>();
service.CallBase = true;
service.Setup(m => m.GetSubjects(1)).Returns(...);
var rank = service.GetRank(1);
// you don't need .VerifyAll call, you didn't not set any expectations on mock
Assert.AreEqual(1, rank, "GetRank method fails");
2. Mocking internal service (ISubjectRepository)
Partial mocks are reserved for special cases. Your case is rather common one. Instead of mocking itself, your component (StudentService) could rely on mocked ISubjectRepository to provide subjects for it:
using (var mock = AutoMock.GetStrict())
{
var subjectRepositoryMock = new Mock<ISubjectRepository>();
subjectRepositoryMock.Setup(x => x.GetSubjects(1)).Returns(...);
mock.Provide(subjectRepositoryMock.Object);
var component = mock.Create<StudentService>();
int rank = component.GetRank(1);
// verify is not needed once again
Assert.AreEqual(1, rank, "GetRank method fails");
}
This code works for. Thank you for everyone for support
[TestFixture]
public class StudentServiceTest
{
private Mock<StudentRepository> _studentRepositoryMock;
private Mock<SubjectRepository> _subjectRepositoryMock;
private Mock<StudentService> _studentServiceMock;
[SetUp]
public void Setup()
{
_studentRepositoryMock = new Mock<StudentService>(MockBehavior.Strict);
_subjectRepositoryMock = new Mock<SubjectRepository>(MockBehavior.Strict);
_studentServiceMock = new Mock<StudentService>(_studentRepositoryMock.Object, _subjectRepositoryMock.Object);
_studentServiceMock.CallBase = true;
}
[TearDown]
public void TearDown()
{
}
[Test]
public void GetRankTest()
{
_studentServiceMock.Setup(x => x.GetSubjects(1)).Returns(...);
int rank = component.GetRank(1);
_studentServiceMock.VerifyAll();
Assert.AreEqual(1, rank, "GetRank method fails");
}
}
I guess your GetSubjects method must be declared virtual, otherwise it cannot be mocked.
public virtual IList<Subject> GetSubjects(int studentId)
{
// code here
}

Moq Verify with anonymous type parameter

I have the following test, with supporting classes, but I can't figure out how to verify the call on the dependency.
[TestFixture]
public class AnonymousGenericTypeParameterTests
{
[Test]
public void Test()
{
// Arrange
var dependency = new Mock<IDependency>();
var towns = new List<Town>
{
new Town { Name = "Lifford", County = "Donegal", Country="Ireland", Population = 1658 },
new Town { Name = "Ballyshannon", County = "Donegal", Country="Ireland", Population = 2504 },
new Town { Name = "Buxton", County = "Derbyshire", Country="United Kingdom", Population = 13599 },
};
var sut = new MyClass(dependency.Object);
// Act
sut.DoSomething(towns);
// Assert
// The following line needs to be fixed.
dependency.Verify(d => d.Execute(It.IsAny<IEnumerable<object>>(), It.IsAny<Func<object, decimal?>>()));
}
}
public interface IDependency
{
void Execute<T>(IEnumerable<T> collection, Func<T, decimal?> rateSelector);
}
public class MyClass
{
private readonly IDependency dependency;
public MyClass(IDependency dependency)
{
this.dependency = dependency;
}
public void DoSomething(IEnumerable<Town> towns)
{
var counties = towns.GroupBy(t => new {t.Country,t.County});
foreach (var county in counties)
{
dependency.Execute(county, c => c.Population);
}
}
}
public class Town
{
public string Name { get; set; }
public string County { get; set; }
public int Population { get; set; }
public string Country { get; set; }
}
According to Moq's test output, the performed invocations are:
Dependency.Execute(System.Linq.Lookup`2+Grouping[<>f__AnonymousType0`2[System.String,System.String],UniFocus.Staffscope4.Tests.Town], System.Func`2[UniFocus.Staffscope4.Tests.Town,System.Nullable`1[System.Decimal]])
I see plenty of questions regarding anonymous parameters in Moq (such as this and this and this), but can't find anything relating to using an anonymous type as the actual type parameter.
What can be put in the Verify line so that it actually verifies the call inside?
Note: My example IDependency doesn't return a value (it's already complex enough, I think), but there will be bonus kudos for answers that implictly or explicitly address Setup() as well as Verify().
Update
Jesse's solution only passes the test because I made a bad choice when crafting my example. I should have realised that any IGrouping<out TKey, out TElement> is also an IEnumerable<TElement>. Is there a more universal solution?
Update 2
I feel like my original example was possibly too elaborate and didn't represent well the actual title of my question. Is there any solution that works for this more straightforward and to-the-point example?
using Moq;
using NUnit.Framework;
namespace Tests
{
[TestFixture]
public class SimpleAnonymousGenericTypeParameterTests
{
[Test]
public void Test()
{
// Arrange
var dependency = new Mock<IDependency>();
var sut = new MyClass(dependency.Object);
// Act
sut.DoSomething("Donegal", "Lifford");
// Assert
// This verify works for both calls to Execute()
dependency.Verify(d => d.Execute(It.IsAny<object>()), Times.Exactly(2));
// This verify should specifically refer to only the first call to Execute()
dependency.Verify(d => d.Execute(It.IsAny</*HowToRepresentAnonymousTypeHere*/object>()), Times.Once);
}
public interface IDependency
{
void Execute<T>(T thing);
}
public class MyClass
{
private readonly IDependency dependency;
public MyClass(IDependency dependency)
{
this.dependency = dependency;
}
public void DoSomething(string county, string town)
{
dependency.Execute(new { county, town });
object someUnknownObject = "";
dependency.Execute(someUnknownObject);
}
}
}
}
The accepted answer doesn't work for me, I believe it's because the tests and the object in question are in a different assembly so Moq doesn't know how to reconcile the types and does not match them.
Instead, I created the following helper methods that can verify that the anonymous type provided has the correct fields and values:
public static class AnonHelpers
{
public static object MatchAnonymousType(object expected)
{
return Match.Create(Matcher(expected));
}
private static Predicate<object> Matcher(object expected)
{
return actual =>
{
var expectedProp = expected.GetType().GetProperties().ToDictionary(x => x.Name, x => x.GetValue(expected));
var actualProp = actual.GetType().GetProperties().ToDictionary(x => x.Name, x => x.GetValue(actual));
foreach (var prop in expectedProp)
{
if (!actualProp.ContainsKey(prop.Key))
return false;
if (!prop.Value.Equals(actualProp[prop.Key]))
return false;
}
return true;
};
}
}
They can be used like so:
var anon = new { SomeKey = "some value", SomeOtherKey = 123 };
myMock.Setup(x => x.MyMethod(personIDs, AnonHelpers.MatchAnonymousType(anon))).Verifiable();
This will create a matcher that will use reflection to match the anonymous type based on it's keys and values and then you can use normal verification to see when it's been called.
Since the types are known in the context of the test, you could provide the specific type arguments to the Verify call. The following change got the test to pass:
dependency.Verify(d =>
d.Execute(It.IsAny<IEnumerable<Town>>(), It.IsAny<Func<Town, decimal?>>()));
The same should also work for setups.
With regards to the example in Update 2, the following passes, but it requires knowledge of the inner workings of the DoSomething() method and as far as I know it's the only way to make it work:
var anonymousType = new {county = "Donegal", town = "Lifford"};
dependency.Verify(d => d.Execute(anonymousType), Times.Once);

C# Unit Test Mocking using Moq.dll

My test case always fails, tell me where I am wrong, Code is below
public class EmployeeService
{
private readonly IRepository _repository;
public EmployeeService(IRepository repository)
{
_repository = repository;
}
public bool SaveEmployeeData(Employee employee,bool isSaveNeeded)
{
bool result = false;
try
{
if (isSaveNeeded)
{
result= _repository.Save(employee);
}
}
catch (Exception ex)
{
throw new Exception();
}
return result;
}
}
And My test case is
[TestMethod()]
public void SaveEmployeeDataTest()
{
var a = new Mock<IRepository>();
a.Setup(s => s.Save(new Employee())).Returns(true).Verifiable();
var result = new EmployeeService(a.Object).SaveEmployeeData(new Employee(), true);
Assert.IsTrue(result);
}
It always fails.
Use It.IsAny<Employee> to setup Save method parameter
a.Setup(s => s.Save(It.IsAny<Employee>())).Returns(true).Verifiable();
The reason why your test not working is because you have two different employee instances - one for mock setup, and one which is passed to SaveEmployeeData method call. By default those instances will be compared by reference. Moq waits for Save method call with employee instance, which have reference 13 (e.g). But you are passing another employee with reference 42. Thus setup is never invoked.
You have two more options
override Equals and GetHashCode methods of Employee class. Thus Moq will compare employees not by reference, but by business data.
use exactly same instance of employee both for mock setup and SaveEmployeeData method call (preferable way)
Usage of same employee instance:
[TestMethod()]
public void SaveEmployeeDataTest()
{
var a = new Mock<IRepository>();
var sameEmployee = new Employee();
a.Setup(s => s.Save(sameEmployee)).Returns(true).Verifiable();
var service = new EmployeeService(a.Object);
var result = service.SaveEmployeeData(sameEmployee, true);
Assert.IsTrue(result);
}
Overriding equality:
public class Employee
{
public override bool Equals(object obj)
{
Employee other = obj as Employee;
if (other == null)
return false;
return this.Id == other.Id; // for example
}
}
In this case you can leave your test as is.
The new Employee() is creating a new employee instance each time, once for the setup of the Save and another for the actual SaveEmployeeData. Because of this, the employee provided never matches the requirements of the setup.
Either use a catch-all approach like lazyberezovsky's answer, or do the following:
[TestMethod()]
public void SaveEmployeeDataTest()
{
var a = new Mock<IRepository>();
var employee = new Employee();
a.Setup(s => s.Save(employee)).Returns(true).Verifiable();
var result = new EmployeeService(a.Object).SaveEmployeeData(employee, true);
Assert.IsTrue(result);
}
Because the same Employee instance is used in the setup as in the actual invocation, the setup is matched and the correct result returned.
try this -
[TestMethod()]
public void SaveEmployeeDataTest()
{
var a = new Mock<IRepository>();
var employee = new Employee();
a.Setup(s => s.Save(employee)).Returns(true).Verifiable();
var result = new EmployeeService(a.Object).SaveEmployeeData(employee, true);
Assert.IsTrue(result);
}
You need to use the same employee instance in setup as well as method call. This would ensure the verification that your are using the same employee instance which is passed in method and not something created in method or returned from another method.

Categories