Mocking method with Action<T> parameter - c#

[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 :)

Related

ServiceBusTrigger Unit testing with XUNIT

I have an Azure Function as below. In the following code, I'm adding a product to the database using Repository & EF Core. Is there any way we can test it using Xunit? Currently, I'm testing this using Azure Service Bus Explorer.
[FunctionName("SaveProductData")]
public void Run([ServiceBusTrigger("mytopicname", Connection = "ServiceBusConnectionString")]
ProductItemUpdate message, ILogger log)
{
var product = new Domain.Entities.Product()
{
... prop init goes here.....
};
log.LogInformation($"Processed Product - Sain: {message.ProductId}");
_productRepository.Add(product);
}
To elaborate on scottdavidwalker's comment with a full example:
public class SaveProductDataTests
{
private readonly Mock<IProductRepository> _mockProductRepository = new Mock<IProductRepository>();
private readonly Mock<ILogger> _mockLogger = new Mock<ILogger>();
private readonly SaveProductData _saveProductData;
public SaveProductDataTests()
{
_saveProductData = new SaveProductData(_mockProductRepository.Object);
}
[Fact]
public void Given_When_Then()
{
// arrange
var productItemUpdate = new ProductItemUpdate();
// act
_saveProductData.Run(productItemUpdate, _mockLogger.Object);
// assert
_mockProductRepository.Verify(x => x.Add(It.Is<Product>(p => p.SomeProperty == "xyz")));
}
}
You need to create an instance of the class you are testing and mock the dependencies.
The Azure function is essentially a method (.Run()) inside the class which you can call on the instance.
In your unit test, you create the data to trigger the method and then make assertions on your mocks for what you expect to happen when the code runs for real.

Mocking (MOQ) passed parameter methods (WebAPI MVC Controller)

My apologies in advanced for not knowing the technical name of this scenario. I am mocking for unit test and that is all fine. However on this section of code I have run into a scenario that exceeds my mocking knowledge. Basically I have MethodA that takes 3 parameters. One of the parameters is passed as another method's output.
When I step through the method passed as a parameter is executed
My difficulty is that the passed method is being executed BEFORE my mocked object. Now it seems like a simple solution...mock the second method as well...that is where my knowledge falls down. I don't know how to get the "second" method mock into the testing context.
My controller being tested (simplified of course):
public class OrderController : ApiController
{
public OrderController(IRepositoryK repositoryk)
{}
public HttpResponseMessage NewOrder()
{
...snip....
string x = repositoryk.MethodA("stuff", "moreStuff", MethodB("junk"));
}
public string MethodB(string data)
{
using (var client = new HttpClient())
{...make call to Google API...}
}
}
My test:
[TestMethod]
public void AddOrder_CorrectResponse()
{
private Mock<IRepositoryK> _repK = new Mock<IRepositoryK>();
_repK.Setup(x => x.MethodA(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns("Yippe");
//of course I've left out all the controller buildup and execution stuff.
}
So I really have no desire to dive into MethodB but it seems to be doing it anyway. What am I doing wrong?
TIA
Thank you for your responses. I understand completely what you are saying. I'm trying to get some testing coverage in place before refactoring. So is there no way of keeping methodB from executing and just let my repositoryK mock just return what I've specified in the setup.
Your code is not easy to test, because it has hard dependency on HttpClient. You have nicely separated repository implementation, but if you want to easily test the code you should also separate code which calls Google API. The idea is to have something like this:
// Add interfece for accessing Google API
public interface IGoogleClient
{
string GetData(string data);
}
// Then implementation is identical to MethodB implementation:
public class GoogleClient : IGoogleClient
{
public string GetData(string data)
{
using (var client = new HttpClient())
{
//...make call to Google API...
}
}
}
// Your controller should look like this:
public class OrderController : ApiController
{
private readonly IRepositoryK repositoryk;
private readonly IGoogleClient googleClient;
public OrderController(IRepositoryK repositoryk, IGoogleClient googleClient)
{
this.googleClient = googleClient;
this.repositoryk = repositoryk;
}
public HttpResponseMessage NewOrder()
{
//...snip....
string x = repositoryk.MethodA("stuff", "moreStuff", MethodB("junk"));
}
public string MethodB(string data)
{
return googleClient.GetData(data);
}
}
If you have such setup you can easily mock both IRepositoryK and IGoogleClient:
Mock<IRepositoryK> repK = new Mock<IRepositoryK>();
Mock<IGoogleClient> googleClient = new Mock<IGoogleClient>();
repK.Setup(x => x.MethodA(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns("Yippe");
googleClient.Setup(It.IsAny<string>()).Returns("something");
var controller = new OrderController(repK.Object, googleClient.Object);
// Test what you want on controller object
However, if you want to keep your code tightly coupled you can mock the call to MethodB with small changes.
First, you need to make method MethodB virtual, so it could be overridden in mock:
public virtual string MethodB(string data)
{
// your code
}
Then in your test instead of instantiating controller, instantiate and use mock of your controller:
var repK = new Mock<IRepositoryK>();
// create mock and pass the same constructor parameters as actual object
var controllerMock = new Mock<OrderController>(repK.Object);
controllerMock.CallBase = true;
// mock MethodB method:
controllerMock.Setup(x => x.MethodB(It.IsAny<string>())).Returns("data");
// call the method on mock object
// instead of calling MethodB you will get a mocked result
var result = controllerMock.Object.NewOrder();

Verify a method is called or not in Unit Test

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.

How to unit test an ICommand that generates a task

I am trying to unit test my viewmodel and I have many commands that simply create a new task and call a service method and using a continuation gets the results and binds them to properties on the viewmodel. I'm fairly new to unit testing and not sure how I would test this scenario. Since its running in a task the assert in my test happens before the service call finishes and before I can set any properties on my viewmodel. Is this how i should unit test my viewmodel?
public ICommand GetItems
{
if(this.Category != null)
{
Task<List<Item>> t = new Task<List<Item>>((o) =>
{
return _service.GetItems(this.Category);
}
t.ContinueWith((task) =>
{
this.Items = task.Result;
}
t.Start();
}
}
[TestMethod]
public void TestGetItems()
{
var selectedCategory = Category.NewItems;
var expected = new List<Item>(){ new Item(){ Value = "ExpectedValue" } };
var service = new Mock<IService>();
service.Setup(i => i.GetItems(selectedCategory)).Returns(expected);
var sut = new MainViewModel(_service.Object);
sut.Category = selectedCategory;
sut.GetItems.Execute(null);
Assert.AreEqual(expected, sut.Items);
}
I recommend creating an Async Command that can abstract out the need for a background task. See here for one example Asynchronous WPF Commands.
If you choose to, you could also modify your OnProperyChanged function to Dispatch property changes to the UI thread.
This pattern has worked for me in the past, and it simplifies the ViewModel code quite a bit.
This way you could test it as you would any other function.

Should I test if a stubbed method was called?

I'm just starting out with BDD/TDD using MSpec (with AutoMocking by James Broome) and RhinoMocks. Here's an excerpt from my practice project:
namespace Tests.VideoStore.Controllers
{
public abstract class context_for_movie_controller :
Specification<MovieController>
{
private static IList<Movie> movies;
protected static IMovieRepository _movieRepository;
protected static ActionResult _result;
protected static string title;
protected static string director;
Establish context = () =>
{
_movieRepository = DependencyOf<IMovieRepository>();
};
}
[Subject(typeof(MovieController))]
public class when_searching_for_movies_with_director :
context_for_movie_controller
{
Establish context = () =>
{
title = null;
director = "James Cameron";
var movie4 = new Movie {
Title = "Terminator", Director = "James Cameron"};
var movie6 = new Movie {
Title = "Avatar", Director = "James Cameron"};
movies = new List<Movie> {movie4, movie6};
// Repository returns all movies.
_movieRepository.Stub(x => x.FindMovies(title, director))
.Return(movies);
};
Because of = () => _result = subject.Find(title, director);
It should_fetch_movies_from_the_repository = () =>
_movieRepository.AssertWasCalled(x =>
x.FindMovies(title, director));
It should_return_a_list_of_movies_matching_the_director = () =>
_result.ShouldBeAView().And()
.ShouldHaveModelOfType<IEnumerable<Movie>>)
.And().ShouldContainOnly(movies);
}
As you can see, I stubbed out the FindMovies() method on the MovieRepository class. Then I'm calling the MoviesController.Find() action. My question is, should there be an assert to check if the stubbed method (FindMovies) was called by the controller? Or perhaps should I only care about the returned result and not where it was taken from? Furthermore, a spec that says "should_fetch_movies_from_the_repository" looks a lot like an engineering task, not something that a client might understand - does it have its place in BDD?
the general rule to follow for assertions is that you assert against output interactions, not input interactions.
the FindMovies stub is returning a "movies" collection to the class that called it and you are then verifying that the class received the correct list via the "it should return a list of movies matching the director" assertion. if the FindMovies method is not called, then this assertion will fail.
therefore, you do not need to assert the calls against the FindMovies method.
to counterpoint this, if you have an mock or stub that is purely output - let's say an IView interface being called by a Presenter class, then you do want to assert against the IView being called. for example, this code:
public class MyPresenter
{
... other code here
public DoSomething()
{
IList data = GetSomeData();
myView.DisplayData(data);
}
}
you would want to assert that the view.DisplayData method is called in this case, because you are not retrieving anything from this call that can be asserted by another test.
as for the "fetch from repository" - of course your customers care about that. they want the system to save movies to the storage and load them from the storage. however ... the FindMovies call is an input into the class being tested, so it's not necessary to have this assetion or test, at all. if the FindMovies method is not called, then the other test will fail and let you know that there is a problem.

Categories

Resources