I have a unit test I am checking whether a method is called once or not so I attempted this way:-
This is my Mock of ILicenseManagerService and I am passing its object through constructor.
public Mock<ILicenseManagerService> LicenseManagerService { get { return SetLicenseManagerServiceMock(); } }
private Mock<ILicenseManagerService> SetLicenseManagerServiceMock()
{
var licencemangerservicemock = new Mock<ILicenseManagerService>();
licencemangerservicemock.Setup(m => m.LoadProductLicenses()).Returns(ListOfProductLicense).Verifiable();
return licencemangerservicemock;
}
public static async Task<IEnumerable<IProductLicense>> ListOfProductLicense()
{
var datetimeoffset = new DateTimeOffset(DateTime.Now);
var lst = new List<IProductLicense>
{
GetProductLicense(true, datetimeoffset, false, "1"),
GetProductLicense(true, datetimeoffset, false, "2"),
GetProductLicense(true, datetimeoffset, true, "3")
};
return lst;
}
I am using this mock object to set _licenseManagerService and calling the LoadProductLicenses() in method under test. like this. licences are coming fine.
var licenses = (await _licenseManagerService.LoadProductLicenses()).ToList();
My attempt for verify the call to this method -
LicenseManagerService.Verify(m => m.LoadProductLicenses(),Times.Once);
But when I run my unit test, an exception coming that say method is not invoked at all.
Where I am doing wrong ?
EDIT #dacastro I am invoking the same mock here is my unit test.
[TestMethod]
[TestCategory("InApp-InAppStore")]
public async Task return_products_from_web_when_cache_is_empty()
{
// this class basically for setting up external dependencies
// Like - LicenceManagerService in context, i am using this mock only no new mock.
var inAppMock = new InAppMock ();
// object of Class under test- I used static method for passing external
//services for easy to change
var inAppStore = StaticMethods.GetInAppStore(inAppMock);
// method is called in this method
var result = await inAppStore.LoadProductsFromCacheOrWeb();
// like you can see using the same inAppMock object and same LicenseManagerService
inAppMock.LicenseManagerService.Verify(m => m.LoadProductLicenses(),Times.Once);
}
LicenseManagerService.Verify(m => m.LoadProductLicenses(),Times.Once);
By calling the LicenseManagerService property, you're creating a new mock object. Naturally, no invocations have ever been performed on this instance.
You should change this property's implementation to return the same instance every time it is called.
Related
Problem
I want to unit test a method in my repository class that checks if a record should be updated or created new.
How do I test the main function without actually having the unit test attempt to insert or query the db?
Code
I have the following repository class:
public class WidgetRepository()
{
public bool InsertOrUpdateWidget(Widget widgetToEval)
{
var retval = false;
var existingRecord = FindExistingWidget(widgetToEval);
if (existingRecord == null)
{
retval = InsertNewWidget(widgetToEval);
}
else
{
retval = UpdateExistingWidget(widgetToEval, existingRecord);
}
return retval;
}
Unit Test
[Fact]
public void Insert_New_Widget()
{
var repo = GetEmptyRepository();
var newWidget = new Widget()
{
ID = 1,
Name= "test",
Description= "Test widget",
};
var result = repo.InsertOrUpdateWidget(newWidget);
Assert.True(result);
}
private IWidgetRepository GetEmptyRepository()
{
var repo = new Mock<IWidgetRepository >();
repo.Setup(s => s.FindExistingWidget(It.IsAny<Widget>())).Returns((Widget)null);
repo.Setup(s => s.InsertNewWidget(It.IsAny<Widget>())).Returns(true);
return repo.Object;
}
In the unit test, I'm trying to mock the FindExistingWidget method and have it return a null object. I've also mocked the insert function and have it return a true.
When I run this test, instead of returning a true, it returns false.
Edit 1
So I understand that I shouldn't mock the repo... I should just create an object of this type because I should only mock things my code needs / dependencies.
But I guess the question is then how do i prevent the code from actually attempting to connect to the db when it runs the FindExistingWidget() method or the actual InsertNewWidget method?
I just want to unit the test the logic inside the InsertorUpdate method to make sure its doing the right thing
When you want to test your repository you don't test the interface. You mock your repo when you want you want to test somehting using it. It's 'unit' test so you should test every method while it's sepereated from the others.
You should be testing WidgetRepository and not IWidgetRepository.
As the previous answers states, you are not Mocking the call to InsertOrUpdateWidget(), so its returning false (it's not even calling the code in the concrete class)
If you are going to mock your repository and you just want it to return true, then do this;
private IWidgetRepository GetEmptyRepository()
{
var repo = new Mock<IWidgetRepository >();
repo.Setup(s => s.InsertOrUpdateWidget(It.IsAny<Widget>())).Returns(true);
return repo.Object;
}
You can't mock just a portion of the WidgetRepository class. In the instance you are using above is your mock, and based on your setup above, you did not implement the function you are calling (InsertOrUpdateWidget) with repo.Setup. Since it returns a boolean, it will default to the value false. This function may be implemented in your concrete implementation of IWidgetRepository, but it isn't in your mock. The return statement return repo.Object; is not of WidgetRepository, but of a mocked version of IWidgetRepository. These are two different implementations, and only one of them implements InsertOrUpdateWidget. It isn't the one you are testing.
I am trying to mock my service's create method like this in the class constructor:
serviceMock.Setup(p => p.AddClinic(GetTestClinicModel()))
.Returns(GetTestClinic());
Mock Model and Mock Entity
private CreateClinicBindingModel GetTestClinicModel()
{
return new CreateClinicBindingModel()
{
Name = "Clinic-3"
};
}
private Clinic GetTestClinic()
{
return new Clinic()
{
Id = 3,
Name = "Clinic-3"
};
}
Test Method
[Fact]
public void Add_ValidObjectPassed_ReturnsCreatedResponse()
{
// Act
var createdResponse = controller.Add(GetTestClinicModel());
// Assert
Assert.IsType<CreatedAtActionResult>(createdResponse);
}
Controller Add Method
[HttpPost("create")]
public IActionResult Add(CreateClinicBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
var entity = _service.AddClinic(model);
return Created(entity);
}
So my problem is test getting failure and when I debug _service.AddClinic() method it returns null.
The mock service does not return the expected Entity (Clinic).
How can I solve this?
The issue is that the setup expects the specific instance created when GetTestClinicModel() is invoked.
However that same instance is not used when exercising the test as a totally new instance is created when GetTestClinicModel() is invoked again.
Thus the mock will return null since there are separate instances.
Consider changing the setup to use an argument matcher like It.Is<T>()
serviceMock
.Setup(_ => _.AddClinic(It.Is<CreateClinicBindingModel>(m => m.Name == "Clinic-3")))
.Returns(GetTestClinic());
The above setup tells the mock to behave as expected when it gets an instance that matches the provided predicate
I'm having a difficult time trying to understand how to appropriately return mocked data from a simulated database call in a unit test.
Here's an example method I want to unit test (GetBuildings):
public class BuildingService : IBuildingService {
public IQueryable<Building> GetBuildings(int propertyId)
{
IQueryable<Building> buildings;
// Execution path for potential exception thrown
// if (...) throw new SpecialException();
// Another execution path...
// if (...) ...
using (var context = DataContext.Instance())
{
var Params = new List<SqlParameter>
{
new SqlParameter("#PropertyId", propertyId)
};
// I need to return mocked data here...
buildings = context
.ExecuteQuery<Building>(System.Data.CommandType.StoredProcedure, "dbo.Building_List", Params.ToArray<object>())
.AsQueryable();
}
return buildings;
}
}
So GetBuildings calls a stored procedure.
So I need to mock the DataContext, that of which I can override and set a testable instance. So what happens here is, in the above example DataContext.Instance() does return the mocked object.
[TestFixture]
public class BuildingServiceTests
{
private Mock<IDataContext> _mockDataContext;
[SetUp]
public void Setup() {
_mockDataContext = new Mock<IDataContext>();
}
[TearDown]
public void TearDown() {
...
}
[Test]
public void SomeTestName() {
_mockDataContext.Setup(r =>
r.ExecuteQuery<Building>(CommandType.StoredProcedure, "someSproc"))
.Returns(new List<Building>() { new Building() { BuildingId = 1, Title = "1" }}.AsQueryable());
DataContext.SetTestableInstance(_mockDataContext.Object);
var builings = BuildingService.GetBuildings(1, 1);
// Assert...
}
Please ignore some of the parameters, like propertyId. I've stripped those out and simplified this all. I simply can't get the ExecuteQuery method to return any data.
All other simple peta-poco type methods I can mock without issue (i.e. Get, Insert, Delete).
Update
DataContext.Instance returns the active instance of the DataContext class, if exists, and if not exists, returns a new one. So the method of test under question returns the mocked instance.
Do not mock DataContext. Because mocking DataContext will produce tests tightly coupled to the implementation details of DataContext. And you will be forced to change tests for every change in the code even behavior will remain same.
Instead introduce a "DataService" interface and mock it in the tests for BuildingService.
public interface IDataService
{
IEnumerable<Building> GetBuildings(int propertyId)
}
Then, you can tests implementation of IDataService agains real database as part of integration tests or tests it agains database in memory.
If you can test with "InMemory" database (EF Core or Sqlite) - then even better -> write tests for BuildingService against actual implementation of DataContext.
In tests you should mock only external resources (web service, file system or database) or only resources which makes tests slow.
Not mocking other dependencies will save you time and give freedom while you refactoring your codebase.
After update:
Based on the updated question, where BuildingService have some execution path - you can still testing BuildingService and abstract data related logic to the IDataService.
For example below is BuildingService class
public class BuildingService
{
private readonly IDataService _dataService;
public BuildingService(IDataService dataService)
{
_dataService = dataService;
}
public IEnumerable<Building> GetBuildings(int propertyId)
{
if (propertyId < 0)
{
throw new ArgumentException("Negative id not allowed");
}
if (propertyId == 0)
{
return Enumerable.Empty<Building>();
}
return _myDataService.GetBuildingsOfProperty(int propertyId);
}
}
In tests you will create a mock for IDataService and pass it to the constructor of BuildingService
var fakeDataService = new Mock<IDataContext>();
var serviceUnderTest = new BuildingService(fakeDataService);
Then you will have tests for:
"Should throw exception when property Id is negative"
"Should return empty collection when property Id equals zero"
"Should return collection of expected buildings when valid property Id is given"
For last test case you will mock IDataService to return expected building only when correct propertyId is given to _dataService.GetBuildingsOfProperty method
In order for the mock to return data is needs to be set up to behave as expected given a provided input.
currently in the method under test it is being called like this
buildings = context
.ExecuteQuery<Building>(System.Data.CommandType.StoredProcedure, "dbo.Building_List", Params.ToArray<object>())
.AsQueryable();
Yet in the test the mock context is being setup like
_mockDataContext.Setup(r =>
r.ExecuteQuery<Building>(CommandType.StoredProcedure, "someSproc"))
.Returns(new List<Building>() { new Building() { BuildingId = 1, Title = "1" }}.AsQueryable());
Note what the mock is told to expect as parameters.
The mock will only behave as expected when provided with those parameters. Otherwise it will return null.
Consider the following example of how the test can be exercised based on the code provided in the original question.
[Test]
public void SomeTestName() {
//Arrange
var expected = new List<Building>() { new Building() { BuildingId = 1, Title = "1" }}.AsQueryable();
_mockDataContext
.Setup(_ => _.ExecuteQuery<Building>(CommandType.StoredProcedure, It.IsAny<string>(), It.IsAny<object[]>()))
.Returns(expected);
DataContext.SetTestableInstance(_mockDataContext.Object);
var subject = new BuildingService();
//Act
var actual = subject.GetBuildings(1);
// Assert...
CollectionAssert.AreEquivalent(expected, actual);
}
That said, the current design of the system under test is tightly coupled to a static dependency which is a code smell and makes the current design follow some bad practices.
The static DataContext which is currently being used as a factory should be refactored as such,
public interface IDataContextFactory {
IDataContext CreateInstance();
}
and explicitly injected into dependent classes instead of calling the static factory method
public class BuildingService : IBuildingService {
private readonly IDataContextFactory factory;
public BuildingService(IDataContextFactory factory) {
this.factory = factory
}
public IQueryable<Building> GetBuildings(int propertyId) {
IQueryable<Building> buildings;
using (var context = factory.CreateInstance()) {
var Params = new List<SqlParameter> {
new SqlParameter("#PropertyId", propertyId)
};
buildings = context
.ExecuteQuery<Building>(System.Data.CommandType.StoredProcedure, "dbo.Building_List", Params.ToArray<object>())
.AsQueryable();
}
return buildings;
}
}
This will allow for a proper mock to be created in injected into the subject under test without using a static workaround hack.
[Test]
public void SomeTestName() {
//Arrange
var expected = new List<Building>() { new Building() { BuildingId = 1, Title = "1" }}.AsQueryable();
_mockDataContext
.Setup(_ => _.ExecuteQuery<Building>(CommandType.StoredProcedure, It.IsAny<string>(), It.IsAny<object[]>()))
.Returns(expected);
var factoryMock = new Mock<IDataContextFactory>();
factoryMock
.Setup(_ => _.CreateInstance())
.Returns(_mockDataContext.Object);
var subject = new BuildingService(factoryMock.Object);
//Act
var actual = subject.GetBuildings(1);
// Assert...
CollectionAssert.AreEquivalent(expected, actual);
}
[unit testing newbie] [c#]
Consider the following scenario:
I'm using Silverlight and calling a WCF service. Silverlight can only call WCF services asynchronously. I build a wrapper around the WCF service so that I can work with Action parameters. (makes the client code a lot cleaner).
So I have an async service that retrieves meeting rooms.
public interface IMeetingRoomService
{
void GetRooms(Action<List<MeetingRoom>> result);
}
Turning GetRooms into List<MeetingRoom> GetRooms() is not an option.
I want to use this service in a ViewModel to set a public property called Rooms.
public class SomeViewModel
{
private readonly IMeetingRoomService _meetingRoomService;
public List<MeetingRoom> Rooms { get; set; }
public SomeViewModel(IMeetingRoomService meetingRoomService)
{
this._meetingRoomService = meetingRoomService;
}
public void GetRooms()
{
// Code that calls the service and sets this.Rooms
_meetingRoomService.GetRooms(result => Rooms = result);
}
}
I want to unit test the implementation of SomeViewModel.GetRooms().
(For this question I quickly wrote the implementation but I'm actually trying to use TDD.)
How do I finish this test?
I'm using NUnit and Moq.
[Test]
public void GetRooms_ShouldSetRooms()
{
var theRooms = new List<MeetingRoom>
{
new MeetingRoom(1, "some room"),
new MeetingRoom(2, "some other room"),
};
var meetingRoomService = new Mock<IMeetingRoomService>();
//How do I setup meetingRoomService so that it gives theRooms in the Action??
var viewModel = new SomeViewModel(meetingRoomService.Object);
viewModel.GetRooms();
Assert.AreEqual(theRooms, viewModel .Rooms);
}
EDIT:
Solution
Read Stephane's answer first.
This is the Test code I ended up writing thanks to stephane's answer:
[Test]
public void GetRooms_ShouldSetRooms()
{
var meetingRoomService = new Mock<IMeetingRoomService>();
var shell = new ShellViewModel(meetingRoomService.Object);
var theRooms = new List<MeetingRoom>
{
new MeetingRoom(1, "some room"),
new MeetingRoom(2, "some other room"),
};
meetingRoomService
.Setup(service => service.GetRooms(It.IsAny<Action<List<MeetingRoom>>>()))
.Callback((Action<List<MeetingRoom>> action) => action(theRooms));
shell.GetRooms();
Assert.AreEqual(theRooms, shell.Rooms);
}
Here is some pseudo code, I haven't run it. But I think that's what you want.
SetupCallback is what you are interested in.
For all the calls to _meetingRoomServiceFake.GetRooms, simply set the _getRoomsCallback to the parameter passed in.
You now have a reference to the callback that you are passing in your viewmodel, and you can call it with whatever list of MeetingRooms you want to test it.
So you can test your asynchronous code almost the same way as synchronous code. it's just a bit more ceremony to setup the fake.
Action<List<MeetingRoom>> _getRoomsCallback = null;
IMeetingRoomService _meetingRoomServiceFake;
private void SetupCallback()
{
Mock.Get(_meetingRoomServiceFake)
.Setup(f => f.GetRooms(It.IsAny<Action<List<MeetingRoom>>>()))
.Callback((Action<List<MeetingRoom>> cb) => _getRoomsCallback= cb);
}
[Setup]
public void Setup()
{
_meetingRoomServiceFake = Mock.Of<IMeetingRoomService>();
SetupCallback();
}
[Test]
public void Test()
{
var viewModel = new SomeViewModel(_meetingRoomServiceFake)
//in there the mock gets called and sets the _getRoomsCallback field.
viewModel.GetRooms();
var theRooms = new List<MeetingRoom>
{
new MeetingRoom(1, "some room"),
new MeetingRoom(2, "some other room"),
};
//this will call whatever was passed as callback in your viewModel.
_getRoomsCallback(theRooms);
}
You could use an AutoResetEvent to handle async calls.
Just initialize it as unset and configure your mock service to set it in the callback.
(IE:
var mockService = new Mock();
mockService.SetUp(x => x.MyMethod()).Returns(someStuff).Callback(() => handle.Set());
)
After that I use hadle.WaitOne(1000) to check if it was called. (IMHO 1000 miliseconds are more than enough to run the async code).
Sorry: This was supposed to go as a reply to the post above... I can't for the life of me figure out how to reply :)
Benn trying to test a service layer method which returns a simple IList using RhinoMocks 3.6
[TestMethod]
public void GetItems_Returns_ActionItemsList()
{
// arrange
var mockRepository = MockRepository.GenerateMock<IActionItemRepository>();
mockRepository.Stub(s => s.Select()).Return(GetFakeActionItems());
var service = new ActionItemQueueService(mockRepository);
// act
var actual = service.GetItems();
mockRepository.VerifyAllExpectations();
// assert
Assert.IsInstanceOfType(actual, typeof(IList<ActionItem>));
}
Real simplle right?
The GetFakeActionItems method for reference;
internal IQueryable<ActionItem> GetFakeActionItems()
{
return new List<ActionItem> {
new ActionItem{
Id = 5,
ClientName = "Bank of American Corporation",
ActionNeeded = RequiredAction.Change,
RecordIndicator = "ROI",
RequestDate = DateTime.Now.AddDays(-3)
}
} as IQueryable<ActionItem>;
}
Here is the class and method under test...
public class ActionItemQueueService : IActionQueueService
{
private readonly IActionItemRepository _actionItemRepository;
public ActionItemQueueService(IActionItemRepository actionItemRepository)
{
_actionItemRepository = actionItemRepository;
if (_actionItemRepository == null)
{
throw new ArgumentNullException("ActionItemRepository");
}
}
public IList<Model.ActionItem> GetItems()
{
return _actionItemRepository.Select().ToList<Model.ActionItem>();
}
}
Nothing wild....
When I run my test, I Get an ArgumentNullException when the GetItems() method is called when _actionItemRepository.Select() fires. Value cannot be null.
Parameter name: source.
Confused and perplexed wondering if anyone has any insight into what I am missing.
Many thanks!
I believe the problem is that you are taking your List<ActionItem> and performing "as IQueryable<ActionItem>" on it in your GetFakeActionItems method. This returns null as it is not a valid conversion.
Thus, when your mock ActionItemRepository runs the stubbed out Select() it returns null (via GetFakeActionItems), which causes the subsequent ToList<Model.ActionItem>() to go down in flames with the ArgumentNullException.
What you actually want to do in your GetFakeActionItems is:
myList.AsQueryable()